Skip to content

Clang compiles ebpf skips the judgment causing the program to fail to load #62849

Open
@g0dA

Description

@g0dA

ENV

kernel: 6.3.1-arch1-1
Clang: 15.0.7 x86_64-pc-linux-gnu

Code

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

struct trace_event_raw_sys_enter {
	short unsigned int type;
	unsigned char flags;
	unsigned char preempt_count;
	int pid;
	int __syscall_nr;
	long unsigned int args[6];
	char __data[0];
};
struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__uint(max_entries, 1);
	__type(key, unsigned int);
	__type(value, char [4096]);
} map SEC(".maps");

SEC("tracepoint/syscalls/sys_enter_execve")
int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter *ctx)
{

	int key = 0 ;
	char *buf = (char *)bpf_map_lookup_elem(&map, &key);	// get ptr of inner buffer
	if (buf == 0)
		return 0;

	char *ptr_name = (char *)ctx->args[0];
	char **argv = (char **)ctx->args[1];
	char *ptr_argv0;
	bpf_probe_read(&ptr_argv0, sizeof(ptr_argv0), argv + 0);

	/* read filename into buffer */
	unsigned int offset = bpf_probe_read_str(buf, 4096, ptr_name);


	/* read argv0 into buffer */
	if (offset > 4096 || offset < 0)
		return 0;
	int len = bpf_probe_read_str(buf + offset, 4096 - offset, ptr_argv0);
	bpf_printk("len : %d\n", len);
	return 0;
}

compile this code with clang -O2 -g -target bpf -c llvbpf.c -o llvbpf.o and load this ebpf by sudo bpftool prog load -L -d llvbpf.o

occur error:

29: (bf) r2 = r7                      ; R2_w=scalar(id=4,umax=8191,var_off=(0x0; 0x1fff)) R7_w=scalar(id=4,umax=8191,var_off=(0x0; 0x1fff))
30: (85) call bpf_probe_read_str#45
invalid access to map value, value_size=4096 off=0 size=8191
R1 min value is outside of the allowed memory range

Reason

in source code:

int len = bpf_probe_read_str(buf + offset, 4096 - offset, ptr_argv0);

in bytecode:

      21:	bf 01 00 00 00 00 00 00	r1 = r0
      22:	67 01 00 00 20 00 00 00	r1 <<= 32
      23:	77 01 00 00 20 00 00 00	r1 >>= 32
      24:	25 01 0b 00 00 10 00 00	if r1 > 4096 goto +11 <LBB0_3>
      25:	1f 07 00 00 00 00 00 00	r7 -= r0  // 4096 - offset
      26:	0f 16 00 00 00 00 00 00	r6 += r1 // buf + offset
      27:	79 a3 f0 ff 00 00 00 00	r3 = *(u64 *)(r10 - 16)
      28:	bf 61 00 00 00 00 00 00	r1 = r6
      29:	bf 72 00 00 00 00 00 00	r2 = r7
      30:	85 00 00 00 2d 00 00 00	call 45

on line 25, offset is r0, there is no scope constraint after the if judgment, on line 26, offset is r1 is correct
so, the correct line 25 should be: r7 -= r1

Problem

So, why does this problem occur when Clang compiles ebpf?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions