libqcdm: fix heap out-of-bounds read in qcdm_log_item_evdo_pilot_sets_v2_new

Validate the active, candidate, and remaining count fields in
qcdm_log_item_evdo_pilot_sets_v2_new() before parsing the sets.
Ensure the received buffer is large enough to contain the number of
sets claimed by the counts.

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/work_items/1070

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
This commit is contained in:
Aleksander Morgado
2026-07-13 10:59:28 +02:00
committed by Aleksander Morgado
parent e9932bde9d
commit 96cb590724
+16
View File
@@ -88,6 +88,7 @@ qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_erro
QcdmResult *result = NULL;
DMLogItemEvdoPilotSetsV2 *pilot_sets;
DMCmdLog *log_cmd = (DMCmdLog *) buf;
size_t avail;
size_t sets_len;
qcdm_return_val_if_fail (buf != NULL, NULL);
@@ -97,6 +98,21 @@ qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_erro
pilot_sets = (DMLogItemEvdoPilotSetsV2 *) log_cmd->data;
/* check_log_item() guarantees len >= sizeof (DMCmdLog) + sizeof (DMLogItemEvdoPilotSetsV2),
* so 'avail' cannot underflow. */
/* Ensure the flexible sets[] array actually contains as many entries as
* the header claims; the modem fully controls these counts. */
avail = len - sizeof (DMCmdLog) - sizeof (DMLogItemEvdoPilotSetsV2);
sets_len = ((size_t) pilot_sets->active_count
+ (size_t) pilot_sets->candidate_count
+ (size_t) pilot_sets->remaining_count)
* sizeof (DMLogItemEvdoPilotSetsV2Pilot);
if (sets_len > avail) {
if (out_error)
*out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH;
return NULL;
}
result = qcdm_result_new ();
sets_len = pilot_sets->active_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot);