Skip to content

Commit 6a495e3

Browse files
authored
[XPTI] Fix data races in tracepoint lookup and deletion (#21874)
Several functions in the Tracepoints class accessed MUID64Check and dereferenced tracepoint pointers without holding MTracepointMutex, allowing use-after-free when concurrent threads perform lookups (xptiLookupEvent) and deletions (xptiDeleteTracepoint). Fixes: - lookupEventData: acquire shared lock before MUID64Check access - releaseEvent: acquire exclusive lock before MUID64Check access (was only locked for the erase/delete, not the preceding check) - isValidUID64: acquire shared lock before MUID64Check access - deleteTracepoint: move TP->MUId read inside the exclusive lock - findEvent, queryPayloadByUID, lookupPayload: move into implemenation into new thread-safe Tracepoints methods
1 parent 929fd90 commit 6a495e3

1 file changed

Lines changed: 66 additions & 44 deletions

File tree

xptifw/src/xpti_trace_framework.cpp

Lines changed: 66 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,8 @@ class Tracepoints {
862862
if (!UId)
863863
return nullptr;
864864

865+
xpti::SharedLock Lock(MTracepointMutex);
866+
865867
if (MUID64Check.count(UId) == 0)
866868
return nullptr;
867869

@@ -914,6 +916,8 @@ class Tracepoints {
914916
if (!Event || Event->unique_id == xpti::invalid_uid)
915917
return;
916918

919+
std::lock_guard<xpti::SharedSpinLock> Lock(MTracepointMutex);
920+
917921
if (MUID64Check.count(Event->unique_id) == 0)
918922
return;
919923

@@ -922,18 +926,15 @@ class Tracepoints {
922926
reinterpret_cast<xpti::TracePointImpl *>(Event->unique_id);
923927

924928
xpti::uid128_t UId = TP->MUId;
925-
{
926-
std::lock_guard<xpti::SharedSpinLock> Lock(MTracepointMutex);
927-
// Find the event list for a given UID
928-
auto &Instances = MTracepoints[UId];
929-
MUID64Check.erase(UId.uid64);
930-
// Now release the event associated with the UID instance
931-
delete Instances[UId.instance];
932-
Instances.erase(UId.instance);
933-
// If there are no more events associated with the UID, we can release
934-
// the Payload as well, but we will not as the same payload may be
935-
// revisited and we need to keep the instance count going
936-
}
929+
// Find the event list for a given UID
930+
auto &Instances = MTracepoints[UId];
931+
MUID64Check.erase(UId.uid64);
932+
// Now release the event associated with the UID instance
933+
delete Instances[UId.instance];
934+
Instances.erase(UId.instance);
935+
// If there are no more events associated with the UID, we can release
936+
// the Payload as well, but we will not as the same payload may be
937+
// revisited and we need to keep the instance count going
937938
}
938939

939940
/// @brief Adds metadata to a trace event.
@@ -1166,9 +1167,9 @@ class Tracepoints {
11661167
return xpti::result_t::XPTI_RESULT_INVALIDARG;
11671168

11681169
{
1169-
xpti::uid128_t UId = TP->MUId;
11701170
// Lock the mutex to ensure thread-safe access to the tracepoints map
11711171
std::lock_guard<xpti::SharedSpinLock> Lock(MTracepointMutex);
1172+
xpti::uid128_t UId = TP->MUId;
11721173
// Find the tracepoint for a given UID
11731174
auto &Instances = MTracepoints[UId];
11741175
// Now release the 64-bit UID associated with tracepoint instance
@@ -1316,7 +1317,55 @@ class Tracepoints {
13161317
/// @return Returns true if the UID exists in the set, indicating it is valid;
13171318
/// otherwise, returns false.
13181319
///
1319-
bool isValidUID64(uint64_t UId) { return (MUID64Check.count(UId) > 0); }
1320+
bool isValidUID64(uint64_t UId) {
1321+
xpti::SharedLock Lock(MTracepointMutex);
1322+
return (MUID64Check.count(UId) > 0);
1323+
}
1324+
1325+
const xpti::trace_event_data_t *findEvent(uint64_t UId) {
1326+
if (UId == xpti::invalid_uid)
1327+
return nullptr;
1328+
1329+
xpti::SharedLock Lock(MTracepointMutex);
1330+
1331+
if (MUID64Check.count(UId) == 0)
1332+
return nullptr;
1333+
1334+
xpti::TracePointImpl *TP = reinterpret_cast<xpti::TracePointImpl *>(UId);
1335+
if (TP && xpti::is_valid_event(&TP->MEvent))
1336+
return &TP->MEvent;
1337+
return nullptr;
1338+
}
1339+
1340+
const xpti::payload_t *queryPayloadByUID(uint64_t UId) {
1341+
if (UId == xpti::invalid_uid)
1342+
return nullptr;
1343+
1344+
xpti::SharedLock Lock(MTracepointMutex);
1345+
1346+
if (MUID64Check.count(UId) == 0)
1347+
return nullptr;
1348+
1349+
xpti::TracePointImpl *TP = reinterpret_cast<xpti::TracePointImpl *>(UId);
1350+
if (TP && xpti::is_valid_payload(&TP->MPayload))
1351+
return &TP->MPayload;
1352+
return nullptr;
1353+
}
1354+
1355+
const xpti_payload_t *lookupPayload(uint64_t UId) {
1356+
if (UId == xpti::invalid_uid)
1357+
return nullptr;
1358+
1359+
xpti::SharedLock Lock(MTracepointMutex);
1360+
1361+
if (MUID64Check.count(UId) == 0)
1362+
return nullptr;
1363+
1364+
xpti::TracePointImpl *TP = reinterpret_cast<xpti::TracePointImpl *>(UId);
1365+
if (TP && xpti::is_valid_payload(&TP->MPayload))
1366+
return TP->payload();
1367+
return nullptr;
1368+
}
13201369

13211370
private:
13221371
/// @brief Registers an event with a given payload and returns the event
@@ -2217,19 +2266,7 @@ class Framework {
22172266
/// nullptr otherwise.
22182267
///
22192268
inline const xpti::trace_event_data_t *findEvent(uint64_t UniversalID) {
2220-
if (UniversalID == xpti::invalid_uid)
2221-
return nullptr;
2222-
2223-
if (MTracepoints.isValidUID64(UniversalID)) {
2224-
xpti::TracePointImpl *TP =
2225-
reinterpret_cast<xpti::TracePointImpl *>(UniversalID);
2226-
if (TP && xpti::is_valid_event(&TP->MEvent))
2227-
return &TP->MEvent;
2228-
else
2229-
return nullptr;
2230-
}
2231-
2232-
return nullptr;
2269+
return MTracepoints.findEvent(UniversalID);
22332270
}
22342271

22352272
///
@@ -2486,26 +2523,11 @@ class Framework {
24862523
}
24872524

24882525
const xpti::payload_t *queryPayloadByUID(uint64_t uid) {
2489-
if (uid == xpti::invalid_uid)
2490-
return nullptr;
2491-
if (!MTracepoints.isValidUID64(uid))
2492-
return nullptr;
2493-
2494-
xpti::TracePointImpl *TP = reinterpret_cast<xpti::TracePointImpl *>(uid);
2495-
if (xpti::is_valid_payload(&TP->MPayload))
2496-
return &TP->MPayload;
2497-
2498-
return nullptr;
2526+
return MTracepoints.queryPayloadByUID(uid);
24992527
}
25002528

25012529
inline const xpti_payload_t *lookupPayload(uint64_t uid) {
2502-
if (!MTracepoints.isValidUID64(uid))
2503-
return nullptr;
2504-
xpti::TracePointImpl *TP = reinterpret_cast<xpti::TracePointImpl *>(uid);
2505-
if (TP && xpti::is_valid_payload(&TP->MPayload))
2506-
return TP->payload();
2507-
else
2508-
return nullptr;
2530+
return MTracepoints.lookupPayload(uid);
25092531
}
25102532

25112533
void printStatistics() {

0 commit comments

Comments
 (0)