-
Notifications
You must be signed in to change notification settings - Fork 20
RDKB-62352 : Observed telemetry2_0 crash #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR updates the HTTP telemetry upload path to better integrate with the RdkCertSelector-based mTLS/PKI stack and to address an observed telemetry2_0 crash when using certificate selection.
Changes:
- Adds OpenSSL crypto initialization in the forked child process when
LIBRDKCERTSEL_BUILDis enabled. - Configures libcurl to use an SSL engine obtained from
rdkcertselector(or the default engine) before performing the HTTP request. - Updates the HTTP protocol library build to link against
libcryptowhenrdkcertselectorsupport is enabled.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
source/protocol/http/curlinterface.c |
Adds OpenSSL initialization and SSL engine configuration to the sendReportOverHTTP child path, and introduces an engine name pointer used with libcurl when LIBRDKCERTSEL_BUILD is enabled. |
source/protocol/http/Makefile.am |
Extends linker flags so libhttp.la links against libcrypto alongside librdkcertselector when cert selector support is enabled, satisfying the new OpenSSL usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
source/protocol/http/curlinterface.c
Outdated
| pEngine = rdkcertselector_getEngine(curlCertSelector); | ||
| if(pEngine != NULL ) { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine); | ||
| if(code != CURLE_OK) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } else { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L); | ||
| if(code != CURLE_OK ) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When LIBRDKCERTSEL_BUILD and ENABLE_RED_RECOVERY_SUPPORT are enabled and state_red_enable is true, curlCertSelectorInit() only initializes curlRcvryCertSelector and leaves curlCertSelector as NULL, but here rdkcertselector_getEngine is always called with curlCertSelector. This can lead to a NULL dereference and also means the SSL engine may not match the selector (thisCertSel) that is later used for rdkcertselector_getCert. To keep the engine and certificate selection consistent and avoid crashes, this should use thisCertSel (with appropriate NULL checks) instead of hard-coding curlCertSelector.
source/protocol/http/curlinterface.c
Outdated
| if(childPid == 0) | ||
| { | ||
| #ifdef LIBRDKCERTSEL_BUILD | ||
| OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL); |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OPENSSL_init_crypto returns a status code indicating whether initialization succeeded, but the return value is currently ignored. For robustness, especially given that subsequent OpenSSL-dependent operations (like engine usage) are required for mTLS, consider checking the return value and at least logging and bailing out early on failure so that errors in crypto initialization are visible and handled deterministically.
| OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL); | |
| if (OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) != 1) | |
| { | |
| T2Error("OPENSSL_init_crypto failed, terminating child process\n"); | |
| exit(EXIT_FAILURE); | |
| } |
source/protocol/http/curlinterface.c
Outdated
| pEngine = rdkcertselector_getEngine(curlCertSelector); | ||
| if(pEngine != NULL ) { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine); | ||
| if(code != CURLE_OK) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } else { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L); | ||
| if(code != CURLE_OK ) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are existing unit tests for sendReportOverHTTP in source/test/protocol/ProtocolTest.cpp, but the new LIBRDKCERTSEL_BUILD-specific behavior here (OpenSSL initialization and SSL engine selection / failure paths) does not appear to be exercised. To prevent regressions in the crash scenario this PR is addressing, it would be helpful to extend the tests to cover the engine selection path (both custom engine and default engine, including error returns from curl_easy_setopt).
pdmooneypub
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see my comments.
source/protocol/http/curlinterface.c
Outdated
| goto child_cleanReturn; | ||
| } | ||
| #ifdef LIBRDKCERTSEL_BUILD | ||
| pEngine = rdkcertselector_getEngine(curlCertSelector); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, from copilot, curlCertSelector is not set when in redrecovery so this could be null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
| goto child_cleanReturn; | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copilot noticed that there were no tests added for the new code paths. can we add unit tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the OpenSSL engine logic is not part of the core telemetry functionality, the telemetry unit test NOT handles the curl request. Based on my understanding, this scenario should be covered under L2/L3 testing rather than as a unit or core telemetry test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
source/protocol/http/curlinterface.c
Outdated
| pEngine = rdkcertselector_getEngine(curlCertSelector); | ||
| if(pEngine != NULL ) { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine); | ||
| if(code != CURLE_OK) { | ||
| childCurlResponse.lineNumber = __LINE__; |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rdkcertselector_getEngine is always called with curlCertSelector, even when thisCertSel has been set to curlRcvryCertSelector for state-red mode and curlCertSelector may have been freed (set to NULL) in curlCertSelectorInit. This can lead to passing a NULL or stale handle into rdkcertselector_getEngine, which is likely the cause of the observed crash and is also inconsistent with the selector actually used later (thisCertSel for rdkcertselector_getCert). Consider calling rdkcertselector_getEngine(thisCertSel) instead (with an appropriate NULL check) so that the engine configuration always matches the active cert selector and avoids dereferencing a freed/NULL selector handle.
source/protocol/http/curlinterface.c
Outdated
| if(curlCertSelector != NULL){ | ||
| rdkcertselector_free(&curlCertSelector); | ||
| curlCertSelector = NULL; |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new block freeing curlCertSelector inside curlCertSelectorInit uses tab indentation, whereas the rest of this function and file use space-based indentation. For consistency with the surrounding code and established style in this file (e.g., the curlRcvryCertSelector initialization and logging below), please switch this block to use the same space-based indentation.
source/protocol/http/curlinterface.c
Outdated
| #ifdef LIBRDKCERTSEL_BUILD | ||
| if(OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) != 1){ | ||
| T2Info("%s, T2:OPENSSL_init_crypto failed.\n", __func__); | ||
| } | ||
| #endif |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The newly added #ifdef LIBRDKCERTSEL_BUILD block before curl_easy_init() is indented with tabs rather than spaces, which is inconsistent with the surrounding code in this function (e.g., the curl = curl_easy_init(); line and subsequent blocks). To follow the file's established indentation style, please re-indent this preprocessor block to use spaces like the rest of the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
source/protocol/http/curlinterface.c
Outdated
| pEngine = rdkcertselector_getEngine(thisCertSel); | ||
| if(pEngine != NULL ) { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine); | ||
| if(code != CURLE_OK) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } else { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L); | ||
| if(code != CURLE_OK ) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new SSL engine selection logic under LIBRDKCERTSEL_BUILD (calling rdkcertselector_getEngine and configuring CURLOPT_SSLENGINE / CURLOPT_SSLENGINE_DEFAULT) does not appear to be covered by existing unit tests, even though this file already has GTest-based coverage for its static helpers (e.g. SetHeader in source/test/protocol/ProtocolTest.cpp). Since this path is specific and error-prone (different behavior depending on whether rdkcertselector_getEngine returns a non-NULL engine, plus the two curl_easy_setopt branches), please consider adding targeted tests that exercise both the engine and default-engine paths and validate the behavior when curl_easy_setopt succeeds or fails.
source/protocol/http/curlinterface.c
Outdated
| pEngine = rdkcertselector_getEngine(thisCertSel); | ||
| if(pEngine != NULL ) { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine); | ||
| if(code != CURLE_OK) { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } else { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L); | ||
| if(code != CURLE_OK ) { | ||
| childCurlResponse.lineNumber = __LINE__; |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this new SSL engine handling block, on CURLOPT_SSLENGINE / CURLOPT_SSLENGINE_DEFAULT failure you only set childCurlResponse.lineNumber before cleaning up and jumping to child_cleanReturn, but you never populate childCurlResponse.curlSetopCode with the failing code. In the parent, the log at lines 633–635 prints curl_easy_strerror(childCurlResponse.curlSetopCode), so these failures will misleadingly appear as CURLE_OK, making debugging much harder. Please set childCurlResponse.curlSetopCode = code in both error branches before the goto child_cleanReturn so the actual failure reason is propagated.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pEngine = rdkcertselector_getEngine(thisCertSel); | ||
| if(pEngine != NULL ) | ||
| { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine); | ||
| if(code != CURLE_OK) | ||
| { | ||
| childCurlResponse.lineNumber = __LINE__; | ||
| curl_easy_cleanup(curl); | ||
| goto child_cleanReturn; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| code = curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L); | ||
| if(code != CURLE_OK ) | ||
| { |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When CURLOPT_SSLENGINE / CURLOPT_SSLENGINE_DEFAULT fail, childCurlResponse.curlSetopCode is not updated before you set lineNumber and jump to child_cleanReturn. This means the parent-side logging will report the last successful setopt result instead of the actual failing CURLcode, making diagnosis harder; consider assigning childCurlResponse.curlSetopCode = code here, consistent with other curl_easy_setopt error paths in this file.
source/protocol/http/curlinterface.c
Outdated
| #ifdef LIBRDKCERTSEL_BUILD | ||
| if(OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) != 1) | ||
| { | ||
| fprintf(stderr, "T2:OPENSSL_init_crypto failed\n"); // avoiding T2 logger in the child. |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the child process, if OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) returns a failure status, the code only prints to stderr but continues to use OpenSSL/cURL as if initialization had succeeded. If OPENSSL_init_crypto ever fails, subsequent crypto/TLS operations are undefined; consider treating this as a hard failure (e.g., set an error in childCurlResponse and jump to child_cleanReturn) so callers get a clear error signal instead of potentially crashing or misbehaving.
| fprintf(stderr, "T2:OPENSSL_init_crypto failed\n"); // avoiding T2 logger in the child. | |
| fprintf(stderr, "T2:OPENSSL_init_crypto failed\n"); // avoiding T2 logger in the child. | |
| childCurlResponse.curlStatus = false; | |
| childCurlResponse.curlResponse = CURLE_FAILED_INIT; | |
| childCurlResponse.lineNumber = __LINE__; | |
| goto child_cleanReturn; |
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
| #include <curl/curl.h> | ||
| #include <signal.h> | ||
| #ifdef LIBRDKCERTSEL_BUILD | ||
| #include <openssl/crypto.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be using openssl api's directly. The libcurl apis should be the only interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shibu, at one point we were hashing the passcode so we could see if it changed (without exposing it). We may want to keep this in here until we have resolved the problem with the passcode.
| if(childPid == 0) | ||
| { | ||
| #ifdef LIBRDKCERTSEL_BUILD | ||
| if(OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG, NULL) != 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be the right thing to do.
No description provided.