Fix OOB reads and infinite loop in TLV and DMAP parsers
pair_ap/pair-tlv.c (pair_tlv_parse): - Add bounds check before reading type and length bytes (i + 2 > length) - Fix off-by-one in chunked TLV scan loop (j + 1 < length) - Add bounds checks inside data copy loop to prevent OOB memcpy - Add else branch to advance index when size == 0 (prevents infinite loop) rtsp.c (handle_set_parameter_metadata): - Require 8 bytes remaining for tag + length fields (off + 8 <= cl) - Validate value length against remaining buffer before read Reported-by: Tristan Madani <tristan@talencesecurity.com> Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
This commit is contained in:
+15
-2
@@ -162,18 +162,21 @@ pair_tlv_parse(const uint8_t *buffer, size_t length, pair_tlv_values_t *values)
|
|||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int ret;
|
int ret;
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
|
if (i + 2 > length)
|
||||||
|
return PAIR_TLV_ERROR_INSUFFICIENT_SIZE;
|
||||||
|
|
||||||
uint8_t type = buffer[i];
|
uint8_t type = buffer[i];
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
uint8_t *data = NULL;
|
uint8_t *data = NULL;
|
||||||
|
|
||||||
// scan TLVs to accumulate total size of subsequent TLVs with same type (chunked data)
|
// scan TLVs to accumulate total size of subsequent TLVs with same type (chunked data)
|
||||||
size_t j = i;
|
size_t j = i;
|
||||||
while (j < length && buffer[j] == type && buffer[j+1] == 255) {
|
while (j + 1 < length && buffer[j] == type && buffer[j+1] == 255) {
|
||||||
size_t chunk_size = buffer[j+1];
|
size_t chunk_size = buffer[j+1];
|
||||||
size += chunk_size;
|
size += chunk_size;
|
||||||
j += chunk_size + 2;
|
j += chunk_size + 2;
|
||||||
}
|
}
|
||||||
if (j < length && buffer[j] == type) {
|
if (j + 1 < length && buffer[j] == type) {
|
||||||
size_t chunk_size = buffer[j+1];
|
size_t chunk_size = buffer[j+1];
|
||||||
size += chunk_size;
|
size += chunk_size;
|
||||||
}
|
}
|
||||||
@@ -188,12 +191,22 @@ pair_tlv_parse(const uint8_t *buffer, size_t length, pair_tlv_values_t *values)
|
|||||||
|
|
||||||
size_t remaining = size;
|
size_t remaining = size;
|
||||||
while (remaining) {
|
while (remaining) {
|
||||||
|
if (i + 2 > length) {
|
||||||
|
free(data);
|
||||||
|
return PAIR_TLV_ERROR_INSUFFICIENT_SIZE;
|
||||||
|
}
|
||||||
size_t chunk_size = buffer[i+1];
|
size_t chunk_size = buffer[i+1];
|
||||||
|
if (chunk_size > length - i - 2) {
|
||||||
|
free(data);
|
||||||
|
return PAIR_TLV_ERROR_INSUFFICIENT_SIZE;
|
||||||
|
}
|
||||||
memcpy(p, &buffer[i+2], chunk_size);
|
memcpy(p, &buffer[i+2], chunk_size);
|
||||||
p += chunk_size;
|
p += chunk_size;
|
||||||
i += chunk_size + 2;
|
i += chunk_size + 2;
|
||||||
remaining -= chunk_size;
|
remaining -= chunk_size;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
i += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = tlv_add_value_(values, type, data, size);
|
ret = tlv_add_value_(values, type, data, size);
|
||||||
|
|||||||
@@ -3275,7 +3275,7 @@ static void handle_set_parameter_metadata(__attribute__((unused)) rtsp_conn_info
|
|||||||
unsigned int off = 8;
|
unsigned int off = 8;
|
||||||
|
|
||||||
uint32_t itag, vl;
|
uint32_t itag, vl;
|
||||||
while (off < cl) {
|
while (off + 8 <= cl) {
|
||||||
// pick up the metadata tag as an unsigned longint
|
// pick up the metadata tag as an unsigned longint
|
||||||
memcpy(&itag, (uint32_t *)(cp + off), sizeof(uint32_t)); /* can be misaligned, thus memcpy */
|
memcpy(&itag, (uint32_t *)(cp + off), sizeof(uint32_t)); /* can be misaligned, thus memcpy */
|
||||||
itag = ntohl(itag);
|
itag = ntohl(itag);
|
||||||
@@ -3286,6 +3286,9 @@ static void handle_set_parameter_metadata(__attribute__((unused)) rtsp_conn_info
|
|||||||
vl = ntohl(vl);
|
vl = ntohl(vl);
|
||||||
off += sizeof(uint32_t);
|
off += sizeof(uint32_t);
|
||||||
|
|
||||||
|
if (vl > cl - off)
|
||||||
|
break;
|
||||||
|
|
||||||
// pass the data over
|
// pass the data over
|
||||||
if (vl == 0)
|
if (vl == 0)
|
||||||
send_metadata('core', itag, NULL, 0, NULL, 1);
|
send_metadata('core', itag, NULL, 0, NULL, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user