-
Notifications
You must be signed in to change notification settings - Fork 334
fix: prevent null deref and OOB read in DLT v2 control handlers (#825, #824) #832
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: master
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 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2105,6 +2105,12 @@ void dlt_daemon_control_get_log_info_v2(int sock, | |||||||||||||||
| DltMessageV2 resp; | ||||||||||||||||
| DltDaemonContext *context = NULL; | ||||||||||||||||
| DltDaemonApplication *application = NULL; | ||||||||||||||||
| /* Local buffers for variable-length apid/ctid parsed from the request. | ||||||||||||||||
| * DltServiceGetLogInfoRequestV2 uses pointer fields (char *apid, char *ctid) | ||||||||||||||||
| * which are NULL after calloc; dlt_set_id_v2 is a no-op on NULL. | ||||||||||||||||
| * Sized DLT_V2_ID_SIZE + 1 so a null terminator is always present (issue #6). */ | ||||||||||||||||
| char req_apid_buf[DLT_V2_ID_SIZE + 1]; | ||||||||||||||||
| char req_ctid_buf[DLT_V2_ID_SIZE + 1]; | ||||||||||||||||
|
|
||||||||||||||||
| int num_applications = 0, num_contexts = 0; | ||||||||||||||||
| uint16_t count_app_ids = 0, count_con_ids = 0; | ||||||||||||||||
|
|
@@ -2151,11 +2157,25 @@ void dlt_daemon_control_get_log_info_v2(int sock, | |||||||||||||||
| db_offset = db_offset + (int)sizeof(uint8_t); | ||||||||||||||||
| memcpy(&(req->apidlen), msg->databuffer + db_offset, sizeof(uint8_t)); | ||||||||||||||||
| db_offset = db_offset + (int)sizeof(uint8_t); | ||||||||||||||||
| dlt_set_id_v2(req->apid, (const char *)(msg->databuffer + db_offset), req->apidlen); | ||||||||||||||||
| if ((int)db_offset + (int)req->apidlen + (int)sizeof(uint8_t) > (int)msg->datasize) { | ||||||||||||||||
| free(req); | ||||||||||||||||
| return; | ||||||||||||||||
| } | ||||||||||||||||
| /* Issue #1: req->apid is NULL after calloc; use local buffer, then point req->apid at it. */ | ||||||||||||||||
| memset(req_apid_buf, 0, sizeof(req_apid_buf)); | ||||||||||||||||
| dlt_set_id_v2(req_apid_buf, (const char *)(msg->databuffer + db_offset), req->apidlen); | ||||||||||||||||
| req->apid = req_apid_buf; | ||||||||||||||||
| db_offset = db_offset + (int)req->apidlen; | ||||||||||||||||
| memcpy(&(req->ctidlen), (const char *)(msg->databuffer + db_offset), sizeof(uint8_t)); | ||||||||||||||||
| db_offset = db_offset + (int)sizeof(uint8_t); | ||||||||||||||||
| dlt_set_id_v2(req->ctid, (const char *)(msg->databuffer + db_offset), req->ctidlen); | ||||||||||||||||
| if ((int)db_offset + (int)req->ctidlen + (int)DLT_ID_SIZE > (int)msg->datasize) { | ||||||||||||||||
| free(req); | ||||||||||||||||
| return; | ||||||||||||||||
| } | ||||||||||||||||
| /* Issue #2: req->ctid is NULL after calloc; use local buffer, then point req->ctid at it. */ | ||||||||||||||||
| memset(req_ctid_buf, 0, sizeof(req_ctid_buf)); | ||||||||||||||||
| dlt_set_id_v2(req_ctid_buf, (const char *)(msg->databuffer + db_offset), req->ctidlen); | ||||||||||||||||
| req->ctid = req_ctid_buf; | ||||||||||||||||
| db_offset = db_offset + (int)req->ctidlen; | ||||||||||||||||
| memcpy((req->com), (const char *)(msg->databuffer + db_offset), DLT_ID_SIZE); | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -3664,12 +3684,17 @@ void dlt_daemon_control_set_log_level_v2(int sock, | |||||||||||||||
| int verbose) | ||||||||||||||||
| { | ||||||||||||||||
| PRINT_FUNCTION_VERBOSE(verbose); | ||||||||||||||||
| char *apid =NULL; | ||||||||||||||||
| char *ctid =NULL; | ||||||||||||||||
| char *apid = NULL; | ||||||||||||||||
| char *ctid = NULL; | ||||||||||||||||
| /* Issue #6: sized DLT_V2_ID_SIZE + 1 so a null terminator is always present | ||||||||||||||||
| * even when dlt_set_id_v2 fills all DLT_V2_ID_SIZE bytes. */ | ||||||||||||||||
| char apid_buf[DLT_V2_ID_SIZE + 1] = {0}; | ||||||||||||||||
| char ctid_buf[DLT_V2_ID_SIZE + 1] = {0}; | ||||||||||||||||
| DltServiceSetLogLevelV2 req = {0}; | ||||||||||||||||
| DltDaemonContext *context = NULL; | ||||||||||||||||
| int8_t apid_length = 0; | ||||||||||||||||
| int8_t ctid_length = 0; | ||||||||||||||||
| /* Issue #5: uint8_t (0-255) avoids negative indices when apidlen/ctidlen >= 128. */ | ||||||||||||||||
| uint8_t apid_length = 0; | ||||||||||||||||
| uint8_t ctid_length = 0; | ||||||||||||||||
| int offset = 0; | ||||||||||||||||
|
|
||||||||||||||||
| if ((daemon == NULL) || (msg == NULL) || (msg->databuffer == NULL)) | ||||||||||||||||
|
|
@@ -3682,11 +3707,24 @@ void dlt_daemon_control_set_log_level_v2(int sock, | |||||||||||||||
| offset = offset + (int)sizeof(uint32_t); | ||||||||||||||||
| memcpy(&(req.apidlen), msg->databuffer + offset, sizeof(uint8_t)); | ||||||||||||||||
| offset = offset + (int)sizeof(uint8_t); | ||||||||||||||||
|
||||||||||||||||
| offset = offset + (int)sizeof(uint8_t); | |
| offset = offset + (int)sizeof(uint8_t); | |
| /* Ensure APID bytes and following CTID length byte are within message bounds */ | |
| if ((offset + req.apidlen + 1) > msg->datasize) | |
| return; |
Copilot
AI
Apr 2, 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.
Missing bounds validation for CTID / trailing fields: after reading req.ctidlen, dlt_set_id_v2(ctid_buf, ...), the subsequent reads of log_level and com assume enough bytes remain. A crafted ctidlen can push offset beyond msg->datasize and cause OOB reads. Add a msg->datasize check covering offset + req.ctidlen + sizeof(log_level) + DLT_ID_SIZE (and validate before calling dlt_set_id_v2).
| offset = offset + (int)sizeof(uint8_t); | |
| offset = offset + (int)sizeof(uint8_t); | |
| /* Validate that CTID, log_level and com fields fit into the received buffer */ | |
| if (dlt_check_rcv_data_size(msg->datasize, | |
| offset + (int)req.ctidlen + (int)sizeof(uint8_t) + DLT_ID_SIZE) < 0) | |
| return; |
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.
Same issue as APID:
DltServiceGetLogInfoRequestV2.ctidis achar *left NULL bycalloc, sodlt_set_id_v2(req->ctid, ...)is a no-op and CTID is never parsed. If CTID filtering is intended, parse into a real buffer and setreq->ctidaccordingly before lookups.