ttusb_dec_process_urb_frame() derives packet_payload_length directly
from bytes in the incoming USB stream and then uses that length to
append data into dec->packet[]. The receive state machine does not
reject oversized packet lengths before it advances to the bulk copy
path, so malformed PVA or SECTION packets can exceed the fixed packet
buffer before packet-specific validation gets a chance to discard them.
Reject packet lengths that cannot fit in dec->packet[] before advancing
the receive state machine to the bulk copy state. Use
pr_warn_ratelimited() when discarding an oversized packet so malformed
streams cannot spam the log.
Found by static analysis.
Compile-tested only.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
v2:
- add the missing Signed-off-by line
- replace raw printk() calls with pr_warn_ratelimited()
- clarify the commit message so it matches the PVA and SECTION bounds
checks in the patch
drivers/media/usb/ttusb-dec/ttusb_dec.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c
index 825a3875989d..a9121fcaa5b9 100644
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -703,17 +703,34 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
if (dec->packet_type == TTUSB_DEC_PACKET_PVA &&
dec->packet_length == 8) {
- dec->packet_state++;
dec->packet_payload_length = 8 +
(dec->packet[6] << 8) +
dec->packet[7];
+ if (dec->packet_payload_length >
+ sizeof(dec->packet) - 4) {
+ pr_warn_ratelimited("%s: packet too long - discarding\n",
+ __func__);
+ dec->packet_state = 0;
+ dec->packet_length = 0;
+ break;
+ }
+ dec->packet_state++;
} else if (dec->packet_type ==
TTUSB_DEC_PACKET_SECTION &&
dec->packet_length == 5) {
- dec->packet_state++;
dec->packet_payload_length = 5 +
((dec->packet[3] & 0x0f) << 8) +
dec->packet[4];
+ if (dec->packet_payload_length >
+ sizeof(dec->packet) - 4 -
+ !!(dec->packet_payload_length % 2)) {
+ pr_warn_ratelimited("%s: packet too long - discarding\n",
+ __func__);
+ dec->packet_state = 0;
+ dec->packet_length = 0;
+ break;
+ }
+ dec->packet_state++;
}
length--;
--
2.50.1 (Apple Git-155)