In the kretprobe/sys_read
probe, I am trying to read the request buffer (user space) in a BPF_MAP_TYPE_ARRAY. The eBPF verifier is throwing the following error:
{"error": "field SyscallProbeRetRead: program syscall__probe_ret_read: load program: permission denied: invalid access to map value, value_size=70 off=0 size=16383: R1 min value is outside of the allowed memory range (truncated, 73 line(s) omitted)"}
LOGIC: If the buf_size is greater than MAX_MSG_SIZE
, then we will read TRACE_PARENT_SIZE
or less (depending on the size of the buffer) into seventy_bytes_array->data
, otherwise, we will not read anything.
#define MAX_MSG_SIZE 16383
#define TRACE_PARENT_SIZE 70
SEC("kretprobe/sys_read")
int syscall__probe_ret_read(struct pt_regs *ctx)
{
size_t buf_size = PT_REGS_RC(ctx);
u64 id = bpf_get_current_pid_tgid();
struct data_args_t *read_args = bpf_map_lookup_elem(&active_read_args_map, &id);
if (read_args)
{
char *buf = read_args->buf;
const u32 keyOne = 0;
struct char_array_value *seventy_bytes_array = bpf_map_lookup_elem(&leftover_buf, &keyOne);
unsigned int overrided_bytes = (buf_size - MAX_MSG_SIZE) > TRACE_PARENT_SIZE ? TRACE_PARENT_SIZE : ((buf_size - MAX_MSG_SIZE) > 0 ? (buf_size - MAX_MSG_SIZE) : 0);
if (overrided_bytes > 0 && buf + MAX_MSG_SIZE && seventy_bytes_array)
{
asm volatile("%[overrided_bytes] &= 0x3fff;\n" ::[overrided_bytes] "+r"(overrided_bytes) :);
bpf_probe_read_user(&seventy_bytes_array, overrided_bytes & 0x3fff, buf + MAX_MSG_SIZE);
}
}
return 0;
}
Declaration of leftover_buf:
struct
{
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, struct char_array_value);
__uint(max_entries, 1);
} leftover_buf SEC(".maps");
Declaration of char_array_value:
struct char_array_value {
char data[TRACE_PARENT_SIZE]; // Replace SIZE with the desired size of your char array
};
Here are the full verifier logs:
599: frame1: R0=map_value_or_null(id=13,off=0,ks=4,vs=70,imm=0) R2=scalar(id=4,umin=16,umax=4294967295,var_off=(0x0; 0xffffffff)) R6=scalar(umin=16384,umax=16453,var_off=(0x4000; 0x7f)) R8=map_value(off=0,ks=8,vs=40,imm=0) R9=map_value(off=0,ks=4,vs=16448,imm=0) R10=fp0 fp-80=mmmm???? fp-88= fp-96=mmmmmmmm fp-104=1
:; unsigned int overrided_bytes = (buf_size - MAX_MSG_SIZE) > TRACE_PARENT_SIZE ? TRACE_PARENT_SIZE : ((buf_size - MAX_MSG_SIZE) > 0 ? (buf_size - MAX_MSG_SIZE) : 0);
:599: (07) r2 += -16383 ; frame1: R2_w=scalar(smin=-16367,smax=4294950912)
:; if (overrided_bytes > 0 && buf + MAX_MSG_SIZE && seventy_bytes_array)
:600: (bf) r1 = r2 ; frame1: R1_w=scalar(id=255,smin=-16367,smax=4294950912) R2_w=scalar(id=255,smin=-16367,smax=4294950912)
:601: (67) r1 <<= 32 ; frame1: R1_w=scalar(smax=9223372032559808512,umax=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min=0,s32_max=0,u32_max=0)
:602: (77) r1 >>= 32 ; frame1: R1_w=scalar(umax=4294967295,var_off=(0x0; 0xffffffff))
:; if (overrided_bytes > 0 && buf + MAX_MSG_SIZE && seventy_bytes_array)
:603: (15) if r1 == 0x0 goto pc+6 ; frame1: R1_w=scalar(umax=4294967295,var_off=(0x0; 0xffffffff))
:604: (15) if r0 == 0x0 goto pc+5 ; frame1: R0=map_value(off=0,ks=4,vs=70,imm=0)
:; asm volatile("%[overrided_bytes] &= 0x3fff;\n" ::[overrided_bytes] "+r"(overrided_bytes) :);
:605: (57) r2 &= 16383 ; frame1: R2_w=scalar(umax=16383,var_off=(0x0; 0x3fff))
:606: (79) r3 = *(u64 *)(r10 -96) ; frame1: R3_w=scalar() R10=fp0 fp-96=mmmmmmmm
:607: (07) r3 += 16383 ; frame1: R3_w=scalar()
:; bpf_probe_read_user(&seventy_bytes_array->data, overrided_bytes & 0x3fff, buf + MAX_MSG_SIZE);
:608: (bf) r1 = r0 ; frame1: R0=map_value(off=0,ks=4,vs=70,imm=0) R1_w=map_value(off=0,ks=4,vs=70,imm=0)
:609: (85) call bpf_probe_read_user#112
:invalid access to map value, value_size=70 off=0 size=16383
:R1 min value is outside of the allowed memory range
:processed 7704 insns (limit 1000000) max_states_per_insn 1 total_states 336 peak_states 336 mark_read 253