-
Notifications
You must be signed in to change notification settings - Fork 3
RDKEMW-12176: btrCore_PopulateListOfPairedDevCrash #60
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?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1364,6 +1364,13 @@ enBTRCoreRet BTRCore_RegisterConnectionIntimationCb (tBTRCoreHandle hBTRCore, fP | |||||||||||||||||||||||||
| /* BTRCore_RegisterConnectionAuthenticationCallback - callback for receiving a connection request from another device */ | ||||||||||||||||||||||||||
| enBTRCoreRet BTRCore_RegisterConnectionAuthenticationCb (tBTRCoreHandle hBTRCore, fPtr_BTRCore_ConnAuthCb afpcBBTRCoreConnAuth, void* apUserData); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #ifdef UNIT_TEST | ||||||||||||||||||||||||||
| gint btrCore_AddAndGetCurrGenForTest(void); | ||||||||||||||||||||||||||
| gint btrCore_GetTerminatorForTest(void); | ||||||||||||||||||||||||||
| void btrCore_SetTerminatorForTest(void); | ||||||||||||||||||||||||||
| void btrCore_ResetTerminatorForTest(void); | ||||||||||||||||||||||||||
|
Comment on lines
1366
to
+1371
|
||||||||||||||||||||||||||
| gint btrCore_AddAndGetCurrGenForTest(void); | |
| gint btrCore_GetTerminatorForTest(void); | |
| void btrCore_SetTerminatorForTest(void); | |
| void btrCore_ResetTerminatorForTest(void); | |
| #ifdef UNIT_TEST | |
| gint btrCore_AddAndGetCurrGenForTest(void); | |
| gint btrCore_GetTerminatorForTest(void); | |
| void btrCore_SetTerminatorForTest(void); | |
| void btrCore_ResetTerminatorForTest(void); | |
| #endif /* UNIT_TEST */ |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -74,6 +74,12 @@ int b_rdk_logger_enabled = 0; | |||||||||||||||
| #define BTRCORE_GOOGLE_OUI_LENGTH 8 | ||||||||||||||||
| #define BTCORE_DEFAULT_CONTROLLER_NAME "Game Controller" | ||||||||||||||||
|
|
||||||||||||||||
| /* Prevent UAF during teardown */ | ||||||||||||||||
| static volatile gint gIsBtrCoreTerminating = 0; | ||||||||||||||||
|
||||||||||||||||
| static volatile gint gIsBtrCoreTerminating = 0; | |
| static gint gIsBtrCoreTerminating = 0; |
Copilot
AI
Mar 24, 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.
gIsBtrCoreTerminating is a module-global flag, so terminating/deinit of one BTRCore handle will affect all handles in the process. Most state in this file is kept per-stBTRCoreHdl, so this introduces cross-instance coupling and can cause hard-to-debug behavior if multiple cores are initialized (or re-initialized) in the same process.
Consider moving the terminating flag into stBTRCoreHdl (per-instance) or switching to an atomic “active handle” pointer check (e.g., g_atomic_pointer_set/get) so calls can be rejected based on which handle is tearing down, rather than globally.
Copilot
AI
Mar 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.
The test helper functions btrCore_AddAndGetCurrGenForTest / btrCore_GetTerminatorForTest are compiled into the main library and exported (not STATIC, not guarded by #ifdef UNIT_TEST). This increases the production ABI surface area and can create accidental dependencies.
Wrap these in #ifdef UNIT_TEST (or similar) and keep them out of non-test builds, or move them to a dedicated test-only compilation unit.
Copilot
AI
Mar 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.
The termination guard is global (gIsBtrCoreTerminating) but does not account for the handle’s generation. Since BTRCore_Init unconditionally resets gIsBtrCoreTerminating back to 0, a new Init happening while an old instance is still tearing down can re-enable work in old threads, reintroducing the UAF scenario. A more robust approach is to validate the handle generation at call sites (e.g., treat a handle as invalid if apsthBTRCore->generation != g_atomic_int_get(&gBtrCoreGenerationCounter)), or use a per-instance termination flag/token rather than a resettable global boolean.
| /* Prevent UAF when worker threads run during teardown */ | |
| if(g_atomic_int_get(&gIsBtrCoreTerminating)) { | |
| BTRCORELOG_WARN("btrCore: Ignoring PopulateListOfPairedDevices during termination\n"); | |
| /* Prevent UAF when worker threads run during teardown or using stale handles */ | |
| if (g_atomic_int_get(&gIsBtrCoreTerminating) || | |
| (apsthBTRCore->generation != g_atomic_int_get(&gBtrCoreGenerationCounter))) { | |
| BTRCORELOG_WARN("btrCore: Ignoring PopulateListOfPairedDevices during termination or generation mismatch\n"); |
Copilot
AI
Mar 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.
New behavior is introduced here (short-circuiting paired-device population during termination), but the diff doesn’t add a focused unit test that sets termination and asserts btrCore_PopulateListOfPairedDevices (or a public wrapper that triggers it) returns enBTRCoreFailure and does not touch freed state. Adding a small targeted test would help prevent regressions of the crash fix.
Copilot
AI
Mar 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.
Resetting gIsBtrCoreTerminating to 0 during BTRCore_Init can race with an in-progress teardown from a previous instance (or concurrent deinit), potentially allowing worker threads from the previous instance to proceed again. Consider removing this global reset and instead deriving ‘terminating’ from a generation/token check (or store a terminating_generation value) so that a new init cannot clear termination state for older generations.
| g_atomic_int_set(&gIsBtrCoreTerminating, 0); |
Copilot
AI
Mar 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.
The teardown gating logic depends on pstlhBTRCore->generation == g_atomic_int_get(&gBtrCoreGenerationCounter), but with the current Init assignment this comparison likely never succeeds. This means gIsBtrCoreTerminating may remain 0 during teardown, defeating the added UAF prevention in btrCore_PopulateListOfPairedDevices. Fix the generation bookkeeping (Init and/or this comparison) so the active instance reliably sets gIsBtrCoreTerminating at the start of BTRCore_DeInit.
| /* Only end global teardown if this is the active generation */ | |
| if (pstlhBTRCore->generation == g_atomic_int_get(&gBtrCoreGenerationCounter)) { | |
| g_atomic_int_set(&gIsBtrCoreTerminating, 1); | |
| } | |
| /* Mark global teardown in progress to prevent UAF in other threads */ | |
| g_atomic_int_set(&gIsBtrCoreTerminating, 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.
btrCore_AddAndGetCurrGenForTestis declared in the publicbtrCore.hAPI surface, but its name/behavior are test-only and it mutates global state (gBtrCoreGenerationCounter). This risks external callers accidentally changing teardown behavior and also couples production ABI to unit-test helpers. Consider moving this declaration to a unit-test-only header (or guarding it with a build define like#ifdef UNIT_TEST), and/or making the symbol non-exported in non-test builds.