Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions arch/x86/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,8 @@ bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs)
off = FIELD_GET(DATA_ARENA_OFFSET_MASK, x->data);
addr = *(unsigned long *)((void *)regs + arena_reg) + off;
bpf_prog_report_arena_violation(is_write, addr, regs->ip);
} else {
bpf_prog_report_probe_violation(is_write, regs->ip);
}

/* jump over faulting load and clear dest register */
Expand Down
1 change: 1 addition & 0 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2902,6 +2902,7 @@ void bpf_dynptr_init(struct bpf_dynptr_kern *ptr, void *data,
void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr);
void bpf_dynptr_set_rdonly(struct bpf_dynptr_kern *ptr);
void bpf_prog_report_arena_violation(bool write, unsigned long addr, unsigned long fault_ip);
void bpf_prog_report_probe_violation(bool write, unsigned long fault_ip);

#else /* !CONFIG_BPF_SYSCALL */
static inline struct bpf_prog *bpf_prog_get(u32 ufd)
Expand Down
18 changes: 18 additions & 0 deletions kernel/trace/bpf_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -2055,6 +2055,24 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)
module_put(mod);
}

void bpf_prog_report_probe_violation(bool write, unsigned long fault_ip)
{
struct bpf_stream_stage ss;
struct bpf_prog *prog;

rcu_read_lock();
prog = bpf_prog_ksym_find(fault_ip);
rcu_read_unlock();
if (!prog)
return;

bpf_stream_stage(ss, prog, BPF_STDERR, ({
bpf_stream_printk(ss, "ERROR: Probe %s access faule, insn=0x%lx\n",
write ? "WRITE" : "READ", fault_ip);
bpf_stream_dump_stack(ss);
}));
}

static __always_inline
void __bpf_trace_run(struct bpf_raw_tp_link *link, u64 *args)
{
Expand Down
22 changes: 21 additions & 1 deletion tools/testing/selftests/bpf/prog_tests/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ static void test_address(struct bpf_program *prog, unsigned long *fault_addr_p)
ASSERT_OK(ret, "ret");
ASSERT_OK(opts.retval, "retval");

sprintf(fault_addr, "0x%lx", *fault_addr_p);
if (fault_addr_p)
sprintf(fault_addr, "0x%lx", *fault_addr_p);

ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDERR, buf, sizeof(buf), &ropts);
ASSERT_GT(ret, 0, "stream read");
Expand Down Expand Up @@ -106,3 +107,22 @@ void test_stream_arena_fault_address(void)

stream__destroy(skel);
}

void test_stream_probe_read_fault(void)
{
struct stream *skel;

#if !defined(__x86_64__)
printf("%s:SKIP: probe fault reporting not supported\n", __func__);
test__skip();
return;
#endif

skel = stream__open_and_load();
if (!ASSERT_OK_PTR(skel, "stream__open_and_load"))
return;

test_address(skel->progs.stream_probe_read_fault, NULL);

stream__destroy(skel);
}
21 changes: 21 additions & 0 deletions tools/testing/selftests/bpf/progs/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "bpf_experimental.h"
#include "bpf_arena_common.h"

#define READ_ONCE(x) (*(volatile typeof(x) *)&(x))

struct arr_elem {
struct bpf_res_spin_lock lock;
};
Expand Down Expand Up @@ -234,4 +236,23 @@ int stream_arena_callback_fault(void *ctx)
return 0;
}

SEC("syscall")
__arch_x86_64
__success __retval(0)
__stderr("ERROR: Probe READ access faule, insn=0x[0-9a-fA-F]+")
__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}")
__stderr("Call trace:\n"
"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n"
"|[ \t]+[^\n]+\n)*}}")
int stream_probe_read_fault(void *ctx)
{
struct sk_buff *skb = bpf_core_cast((void *)0xFFFFFFFF00000000,
struct sk_buff);

/* do the memory read */
READ_ONCE(skb->network_header);

return 0;
}

char _license[] SEC("license") = "GPL";
Loading