perf trace-event: Fix integer truncation in do_read() and skip()

The do_read() and skip() functions use 'int' for size parameters,
truncating 64-bit sizes from callers. This causes two issues:

1. Uninitialized memory dump: do_read() reads fewer bytes than
   allocated, leaving uninitialized heap memory that gets written
   to output files.

2. Out-of-bounds read: Parsing functions process the full 64-bit
   size while only partial data was read into the buffer.

Change do_read(), __do_read(), and skip() to use size_t for size
parameters and ssize_t for return values (where applicable), matching
read()/write() system calls.
Update callers to use ssize_t for storing return values.

Fixes: 4a31e56599 ("perf tools: Get rid of read_or_die() in trace-event-read.c")
Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Tanushree Shah 2026-07-26 00:19:50 +05:30 committed by Namhyung Kim
parent 1121a7af18
commit c108c1391b

View File

@ -25,18 +25,18 @@ static int input_fd;
static ssize_t trace_data_size;
static bool repipe;
static int __do_read(int fd, void *buf, int size)
static ssize_t __do_read(int fd, void *buf, size_t size)
{
int rsize = size;
size_t rsize = size;
while (size) {
int ret = read(fd, buf, size);
ssize_t ret = read(fd, buf, size);
if (ret <= 0)
return -1;
if (repipe) {
int retw = write(STDOUT_FILENO, buf, ret);
ssize_t retw = write(STDOUT_FILENO, buf, ret);
if (retw <= 0 || retw != ret) {
pr_debug("repiping input file");
@ -51,13 +51,13 @@ static int __do_read(int fd, void *buf, int size)
return rsize;
}
static int do_read(void *data, int size)
static ssize_t do_read(void *data, size_t size)
{
int r;
ssize_t r;
r = __do_read(input_fd, data, size);
if (r <= 0) {
pr_debug("reading input file (size expected=%d received=%d)",
pr_debug("reading input file (size expected=%zu received=%zd)",
size, r);
return -1;
}
@ -68,10 +68,10 @@ static int do_read(void *data, int size)
}
/* If it fails, the next read will report it */
static void skip(int size)
static void skip(size_t size)
{
char buf[BUFSIZ];
int r;
size_t r;
while (size) {
r = size > BUFSIZ ? BUFSIZ : size;
@ -202,7 +202,7 @@ static int read_header_files(struct tep_handle *pevent)
unsigned long long size;
char *header_page;
char buf[BUFSIZ];
int ret = 0;
ssize_t ret = 0;
if (do_read(buf, 12) < 0)
return -1;
@ -250,7 +250,7 @@ static int read_header_files(struct tep_handle *pevent)
static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
{
int ret;
ssize_t ret;
char *buf;
buf = malloc(size);
@ -276,7 +276,7 @@ static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
static int read_event_file(struct tep_handle *pevent, char *sys,
unsigned long long size)
{
int ret;
ssize_t ret;
char *buf;
buf = malloc(size);
@ -322,7 +322,7 @@ static int read_event_files(struct tep_handle *pevent)
int systems;
int count;
int i,x;
int ret;
ssize_t ret;
systems = read4(pevent);
@ -350,7 +350,7 @@ static int read_saved_cmdline(struct tep_handle *pevent)
{
unsigned long long size;
char *buf;
int ret;
ssize_t ret;
/* it can have 0 size */
size = read8(pevent);