From 96d381109b10697a1b81aca93e0d6db45e6d09bd Mon Sep 17 00:00:00 2001 From: Leechael Yim Date: Mon, 22 Dec 2025 11:46:41 +0800 Subject: [PATCH] fix(qgs): release context on init failure to enable auto-recovery When QPL fails to retrieve PCK certificates (e.g., HTTP 404 from PCCS), the QGS context was not being released, causing all subsequent quote requests to fail until the service was restarted. This fix ensures context is released on failure at all critical points: qgs_ql_logic.cpp: - Release context when tee_att_init_quote fails (first request) - Release context when tee_att_get_quote_size/get_quote fails (subsequent requests with existing context) network_wrapper.cpp (Linux & Windows): - Add error logging for HTTP 404 (no cache data) with full URL - Add error logging for unexpected HTTP status codes The root cause was that HTTP 404 errors from PCCS (indicating no certificate data available) left the context in a corrupted state. With this fix, the next request will automatically re-initialize the context and retry. --- QuoteGeneration/qcnl/linux/network_wrapper.cpp | 6 +++++- QuoteGeneration/qcnl/win/network_wrapper.cpp | 5 +++++ QuoteGeneration/quote_wrapper/qgs/qgs_ql_logic.cpp | 14 +++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/QuoteGeneration/qcnl/linux/network_wrapper.cpp b/QuoteGeneration/qcnl/linux/network_wrapper.cpp index e53a1e3c0..328feeaf4 100644 --- a/QuoteGeneration/qcnl/linux/network_wrapper.cpp +++ b/QuoteGeneration/qcnl/linux/network_wrapper.cpp @@ -244,6 +244,7 @@ static sgx_qcnl_error_t pccs_status_to_qcnl_error(long pccs_status_code) { case 403: return SGX_QCNL_NETWORK_ERROR; case 404: // PCCS_STATUS_NO_CACHE_DATA + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] PCCS returned HTTP 404: No cache data available for this platform.\n"); return SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA; case 461: // PCCS_STATUS_PLATFORM_UNKNOWN return SGX_QCNL_ERROR_STATUS_PLATFORM_UNKNOWN; @@ -252,6 +253,7 @@ static sgx_qcnl_error_t pccs_status_to_qcnl_error(long pccs_status_code) { case 503: // PCCS_STATUS_SERVICE_UNAVAILABLE return SGX_QCNL_ERROR_STATUS_SERVICE_UNAVAILABLE; default: + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] PCCS returned unexpected HTTP status: %ld\n", pccs_status_code); return SGX_QCNL_ERROR_STATUS_UNEXPECTED; } } @@ -396,8 +398,10 @@ sgx_qcnl_error_t qcnl_https_request(const char *url, qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Encountered CURL error: (%d) %s \n", curl_ret, f_easy_strerror(curl_ret)); ret = curl_error_to_qcnl_error(curl_ret); - } else + } else { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Request failed for URL: %s (HTTP %ld)\n", url, http_code); ret = pccs_status_to_qcnl_error(http_code); + } goto cleanup; } } while (true); diff --git a/QuoteGeneration/qcnl/win/network_wrapper.cpp b/QuoteGeneration/qcnl/win/network_wrapper.cpp index 3f45e5189..748f9f461 100644 --- a/QuoteGeneration/qcnl/win/network_wrapper.cpp +++ b/QuoteGeneration/qcnl/win/network_wrapper.cpp @@ -86,6 +86,7 @@ static sgx_qcnl_error_t pccs_status_to_qcnl_error(DWORD pccs_status_code) { case 200: // PCCS_STATUS_SUCCESS return SGX_QCNL_SUCCESS; case 404: // PCCS_STATUS_NO_CACHE_DATA + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] PCCS returned HTTP 404: No cache data available for this platform.\n"); return SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA; case 461: // PCCS_STATUS_PLATFORM_UNKNOWN return SGX_QCNL_ERROR_STATUS_PLATFORM_UNKNOWN; @@ -94,6 +95,7 @@ static sgx_qcnl_error_t pccs_status_to_qcnl_error(DWORD pccs_status_code) { case 503: // PCCS_STATUS_SERVICE_UNAVAILABLE; return SGX_QCNL_ERROR_STATUS_SERVICE_UNAVAILABLE; default: + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] PCCS returned unexpected HTTP status: %ld\n", pccs_status_code); return SGX_QCNL_ERROR_STATUS_UNEXPECTED; } } @@ -329,9 +331,12 @@ sgx_qcnl_error_t qcnl_https_request_once(const char *url, delete[] lpOutBuffer; } else if (dwStatus == HTTP_STATUS_NOT_FOUND) // 404 { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] PCCS returned HTTP 404: No cache data available for this platform.\n"); + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Request failed for URL: %s (HTTP 404)\n", url); ret = SGX_QCNL_ERROR_STATUS_NO_CACHE_DATA; break; } else { + qcnl_log(SGX_QL_LOG_ERROR, "[QCNL] Request failed for URL: %s (HTTP %lu)\n", url, dwStatus); ret = pccs_status_to_qcnl_error(dwStatus); break; } diff --git a/QuoteGeneration/quote_wrapper/qgs/qgs_ql_logic.cpp b/QuoteGeneration/quote_wrapper/qgs/qgs_ql_logic.cpp index 77838c31f..c933fd5b3 100644 --- a/QuoteGeneration/quote_wrapper/qgs/qgs_ql_logic.cpp +++ b/QuoteGeneration/quote_wrapper/qgs/qgs_ql_logic.cpp @@ -127,6 +127,7 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { tee_att_ret = tee_att_init_quote(ptr.get(), &qe_target_info, false, &hash_size, hash); if (TEE_ATT_SUCCESS != tee_att_ret) { QGS_LOG_ERROR("tee_att_init_quote return 0x%x\n", tee_att_ret); + ptr.reset(); // Release context on failure to allow re-initialization on next request return {}; } else { QGS_LOG_INFO("tee_att_init_quote return success\n"); @@ -194,6 +195,11 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { } // Only retry once when the return code is TEE_ATT_ATT_KEY_NOT_INITIALIZED } while (TEE_ATT_ATT_KEY_NOT_INITIALIZED == tee_att_ret && retry--); + + // Release context on failure to allow re-initialization on next request + if (resp_error_code != QGS_MSG_SUCCESS) { + ptr.reset(); + } } if (resp_error_code == QGS_MSG_SUCCESS) { qgs_msg_error_ret = qgs_msg_gen_get_quote_resp(NULL, 0, quote_buf.data(), size, &p_resp, &resp_size); @@ -370,7 +376,8 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { hash); if (TEE_ATT_SUCCESS != tee_att_ret) { QGS_LOG_ERROR("tee_att_init_quote return 0x%x\n", tee_att_ret); - //ingnore failure + ptr.reset(); // Release context on failure to allow re-initialization on next request + return {}; } else { QGS_LOG_INFO("tee_att_init_quote return success\n"); } @@ -429,6 +436,11 @@ namespace intel { namespace sgx { namespace dcap { namespace qgs { // Only retry once when the return code is TEE_ATT_ATT_KEY_NOT_INITIALIZED } while (TEE_ATT_ATT_KEY_NOT_INITIALIZED == tee_att_ret && retry--); + // Release context on failure to allow re-initialization on next request + if (TEE_ATT_SUCCESS != tee_att_ret) { + ptr.reset(); + } + return resp; } else { QGS_LOG_INFO("Not a legimit raw request, stop\n");