hdmi_spd_infoframe_unpack() hands the raw InfoFrame payload to
hdmi_spd_infoframe_init() as its "vendor" and "product" arguments:
ptr += HDMI_INFOFRAME_HEADER_SIZE;
ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8);
hdmi_spd_infoframe_init() then runs strlen() on both pointers. The SPD
vendor (8 bytes) and product (16 bytes) fields are fixed-length and are
not required to be NUL terminated, so strlen() can read past the end of
the source buffer.
Those bytes originate from an external HDMI source. HDMI receiver
drivers copy the received InfoFrame registers into a local buffer and
pass it to hdmi_infoframe_unpack(); tda1997x_parse_infoframe(), for
instance, reads into an on-stack u8 buffer[40] via io_readn() with no
trailing NUL. A source that leaves the vendor/product bytes
unterminated makes strlen() walk off the end of that buffer.
Bound the scan with strnlen() using the destination field sizes. The
copies were already clamped to sizeof(frame->vendor) and
sizeof(frame->product), so behaviour is unchanged for valid,
NUL-terminated callers; only the over-read on unterminated input is
removed.
Signed-off-by: Naveed Khan <[email protected]>
---
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
index 45b42f14a7..32163576a7 100644
--- a/drivers/video/hdmi.c
+++ b/drivers/video/hdmi.c
@@ -230,10 +230,10 @@ int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe
*frame,
frame->version = 1;
frame->length = HDMI_SPD_INFOFRAME_SIZE;
- len = strlen(vendor);
- memcpy(frame->vendor, vendor, min(len, sizeof(frame->vendor)));
- len = strlen(product);
- memcpy(frame->product, product, min(len, sizeof(frame->product)));
+ len = strnlen(vendor, sizeof(frame->vendor));
+ memcpy(frame->vendor, vendor, len);
+ len = strnlen(product, sizeof(frame->product));
+ memcpy(frame->product, product, len);
return 0;
}
--
2.52.0