Skip to content

daemon: fix OOB read and parse bug in dlt_daemon_control_get_log_info_v2 (closes #870)#861

Open
SoundMatt wants to merge 2 commits into
COVESA:masterfrom
SoundMatt:fix/get-log-info-v2-oob-read
Open

daemon: fix OOB read and parse bug in dlt_daemon_control_get_log_info_v2 (closes #870)#861
SoundMatt wants to merge 2 commits into
COVESA:masterfrom
SoundMatt:fix/get-log-info-v2-oob-read

Conversation

@SoundMatt
Copy link
Copy Markdown

@SoundMatt SoundMatt commented May 5, 2026

Problem

dlt_daemon_control_get_log_info_v2 had two compounding bugs, each
addressed by one commit in this PR.

1. Out-of-bounds read parsing apidlen / ctidlen

The fixed-size precheck only validated the 11-byte minimum
GET_LOG_INFO V2 request before the function read two attacker-
controlled uint8_t length fields (apidlen, ctidlen) and used
them to advance an offset into msg->databuffer. A short message
with non-zero length fields caused the variable-length reads to walk
past the end of msg->databuffer (up to ~514 bytes). Reachable from
any client able to talk to the daemon's control socket. Bounded OOB
read; no OOB write.

2. Function never actually parses apid / ctid (#870)

req is calloc'd, so its char *apid / char *ctid pointer fields
start NULL. The dlt_set_id_v2(req->apid, ...) calls intended to
populate them are no-ops (the helper early-returns when its
destination is NULL). req->apid / req->ctid therefore stayed
NULL and were passed to dlt_daemon_application_find_v2 /
dlt_daemon_context_find_v2 with non-zero corresponding lengths —
turning every non-empty apid / ctid lookup into a zero-length one.
Full analysis in #870.

Fix

Two commits:

  1. Bounds checks after each variable-length field is parsed,
    freeing the calloc'd req and returning when the message cannot
    satisfy the next read.
  2. Replace the no-op dlt_set_id_v2(req->apid, ...) calls with
    conditional pointer assignments
    into msg->databuffer,
    mirroring the surgical approach taken for set_log_level_v2 in
    daemon: parse apid/ctid in dlt_daemon_control_set_log_level_v2 #864 and unregister_context_v2 in daemon: fix multi-bug response builder in dlt_daemon_control_message_unregister_context_v2 (closes #867) #868.

req shares storage with the message buffer for the duration of
this function call, so the pointer-into-databuffer assignments are
lifetime-safe.

Notes

Closes #870.
Related: #866 (META).

The fixed-size precheck at the entry of this function validates only the
11-byte minimum GET_LOG_INFO V2 request (apidlen = ctidlen = 0). The
function then reads two attacker-controlled uint8_t length fields
(apidlen, ctidlen) from msg->databuffer and uses them to advance an
offset, before passing pointers into the buffer to dlt_set_id_v2()
(which reads up to apidlen / ctidlen bytes via dlt_strnlen_s) and
finishing with a 4-byte memcpy of the trailing com field. A short
message with non-zero length fields causes the variable-length reads to
walk past the end of msg->databuffer.

Add bounds checks after each length is parsed, freeing the calloc'd
request and returning when the message cannot satisfy the next read.

Note: the existing early-return paths inside this function already leak
the calloc'd req pointer; left untouched here to keep this commit
focused on the security fix.
Companion fix to the OOB-read fix in this same commit series. The
function never assigned req->apid or req->ctid: req is calloc'd, so
the char * pointer fields start NULL, and the dlt_set_id_v2(req->apid,
...) call to populate them was a no-op (dlt_set_id_v2 early-returns
when its destination is NULL). req->apid / req->ctid stayed NULL and
were then passed to dlt_daemon_application_find_v2 and
dlt_daemon_context_find_v2 despite req->apidlen / req->ctidlen being
non-zero — every non-empty lookup was silently turned into a
zero-length one.

Replace the no-op dlt_set_id_v2 calls with conditional pointer
assignments into msg->databuffer, mirroring the surgical approach
taken for set_log_level_v2 in PR COVESA#864 and unregister_context_v2 in
PR COVESA#868. The bounds checks added in the previous commit ensure the
pointer-into-databuffer assignments are safe.

Closes COVESA#870.
Related: COVESA#866.
@SoundMatt SoundMatt changed the title daemon: fix out-of-bounds read in dlt_daemon_control_get_log_info_v2 daemon: fix OOB read and parse bug in dlt_daemon_control_get_log_info_v2 (closes #870) May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dlt_daemon_control_get_log_info_v2 never assigns req->apid / req->ctid; downstream lookups get NULL pointers

1 participant