[PATCH] media: ttusb-dec: reject oversized packets before copying them

Pengpeng Hou posted 1 patch 2 months, 1 week ago
drivers/media/usb/ttusb-dec/ttusb_dec.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
[PATCH] media: ttusb-dec: reject oversized packets before copying them
Posted by Pengpeng Hou 2 months, 1 week ago
ttusb_dec_process_urb_frame() derives packet lengths from packet
bytes and uses those lengths to drive memcpy() into dec->packet.
That staging buffer is fixed at MAX_PVA_LENGTH + 4 bytes, but the
parser does not currently verify that a PVA or section packet still
fits before it continues copying the rest of the packet.

For PVA packets, the parsed payload length is 8 plus a 16-bit field
and the parser later appends a 4-byte trailer before processing the
packet. For section packets, the parser similarly uses the parsed
payload length and then appends a 4-byte trailer plus one padding byte
for odd-sized payloads. Reject packets whose advertised total staged
length would exceed dec->packet before entering the bulk-copy state.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 drivers/media/usb/ttusb-dec/ttusb_dec.c | 19 +++++++++++++++++--
 1 file changed, 17 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..92259ebe59c6 100644
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -703,17 +703,32 @@ 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 + 4 >
+				    sizeof(dec->packet)) {
+					pr_warn("%s: PVA packet too long - discarding\n",
+						__func__);
+					dec->packet_state = 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 + 4 +
+				    (dec->packet_payload_length % 2) >
+				    sizeof(dec->packet)) {
+					pr_warn("%s: section packet too long - discarding\n",
+						__func__);
+					dec->packet_state = 0;
+					break;
+				}
+				dec->packet_state++;
 			}
 
 			length--;
-- 
2.50.1 (Apple Git-155)