size is read directly from the input file as an unsigned int.
When size == UINT_MAX, malloc(size + 1) overflows to malloc(0),
so malloc(0) returns a minimal allocation while size itself
remains UINT_MAX. do_read(buf, size) then attempts to read
~4 GiB into that tiny buffer, causing a heap buffer overflow.
This was previously masked by do_read()'s size parameter being
'int': passing UINT_MAX truncated it to -1, which the read()
syscall rejected before any data was read. Widening do_read() to
size_t is correct on its own, but it removes this accidental guard
and exposes the pre-existing missing bounds check here.
Fix it by rejecting size == UINT_MAX before the allocation.
Signed-off-by: Tanushree Shah <redacted>
---
tools/perf/util/trace-event-read.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 52ed496d92c3..147a3b95ce06 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -180,6 +180,11 @@ static int read_ftrace_printk(struct tep_handle *pevent)
if (!size)
return 0;
+ if (size == UINT_MAX) {
+ pr_debug("invalid ftrace printk size\n");
+ return -1;
+ }
+
buf = malloc(size + 1);
if (buf == NULL)
return -1;--
2.47.3