From a7205fc9a9022d99c8fcedb99a9472011c6f0058 Mon Sep 17 00:00:00 2001 From: Kornilios Kourtis Date: Tue, 12 Sep 2023 11:22:15 +0200 Subject: [PATCH] bpf: fix verification error in bpf_execve_event This patch fixes a verification error in a 4.18.0-477.21.1.el8_8.x86_64 kernel. The error was reported in issue 1442. The patch simplifies the code: it eliminates a common expression, and it changes some values from int to long to avoid generated code for the implicit casting. It also fixes a issue. bpf_probe_read_str may return 0, and in this case the old code will underflow. And even though we mask the size, the size value would have been wrong in this case: (gdb) printf "0x%zx\n", (0-1) & 0x7fff 0x7fff Signed-off-by: Kornilios Kourtis --- bpf/process/data_event.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/bpf/process/data_event.h b/bpf/process/data_event.h index 4bd954cde51..91ccf889b33 100644 --- a/bpf/process/data_event.h +++ b/bpf/process/data_event.h @@ -79,7 +79,7 @@ static inline __attribute__((always_inline)) long __do_str(void *ctx, struct msg_data *msg, unsigned long arg, bool *done) { size_t size, max = sizeof(msg->arg) - 1; - int err; + long ret; /* Code movement from clang forces us to inline bounds checks here */ asm volatile("%[max] &= 0x7fff;\n" @@ -89,25 +89,25 @@ __do_str(void *ctx, struct msg_data *msg, unsigned long arg, bool *done) : [max] "+r"(max) :); - err = probe_read_str(&msg->arg[0], max, (char *)arg); - if (err < 0) - return err; + ret = probe_read_str(&msg->arg[0], max, (char *)arg); + if (ret < 0) + return ret; - *done = err != max; + *done = ret != max; + if (ret == 0) + return 0; /* cut out the zero byte */ - err -= 1; - - msg->common.size = offsetof(struct msg_data, arg) + err; - - size = err + offsetof(struct msg_data, arg); + ret -= 1; + size = ret + offsetof(struct msg_data, arg); /* Code movement from clang forces us to inline bounds checks here */ asm volatile("%[size] &= 0x7fff;\n" : : [size] "+r"(size) :); + msg->common.size = size; perf_event_output(ctx, &tcpmon_map, BPF_F_CURRENT_CPU, msg, size); - return err; + return ret; } static inline __attribute__((always_inline)) long @@ -116,15 +116,16 @@ do_str(void *ctx, struct msg_data *msg, unsigned long arg, { size_t rd_bytes = 0; bool done = false; - int err, i; + long ret; + int i; #define __CNT 2 #pragma unroll for (i = 0; i < __CNT; i++) { - err = __do_str(ctx, msg, arg + rd_bytes, &done); - if (err < 0) - return err; - rd_bytes += err; + ret = __do_str(ctx, msg, arg + rd_bytes, &done); + if (ret < 0) + return ret; + rd_bytes += ret; if (done) break; }