继续获取 bpf:加载程序失败:尝试 运行 eBPF 代码时权限被拒绝

Keep getting bpf: Failed to load program: Permission denied when trying to run eBPF code

抱歉,我是编写 eBPF 代码的新手,所以我遇到了一个我似乎无法摆脱的错误。 运行 in sudo 似乎没有帮助。我写了一个编译速度较慢的 crc32 程序,但这个程序无论如何都不想执行。我想知道我是否违反了我只是没有看到的任何约定。

bpf_text2 = """
#include <uapi/linux/ptrace.h>

int crc32(struct pt_regs *ctx) {
char str[256] = {};
bpf_probe_read(&str, sizeof(str), (void *)PT_REGS_RC(ctx));
const uint32_t Polynomial = 0xEDB88320;

u64 startTime = bpf_ktime_get_ns();

uint32_t previousCrc32 = 0;
uint32_t crc = ~previousCrc32;
unsigned char* current = 0;

int maxVal = sizeof(str);
while (maxVal--) {
    crc ^= *current++;
    for (unsigned int j = 0; j < 8; j++) {
        crc = (crc >> 1) ^ ((0 - (crc & 1)) & Polynomial);
    }
}
int result = ~crc;
u64 totalTime = bpf_ktime_get_ns() - startTime;

bpf_trace_printk(">> BCC - CRC of `\"%s\" is: 0x%x \n",str, result);
bpf_trace_printk(">> BCC - CRC took: %lu cycles\n", totalTime);
bpf_trace_printk("BCC - Test Complete.\n\n\n");

return 0;
}
"""

也可以快速查看下面的错误消息。

> Compiling BPF
Attaching to uretprobe
bpf: Failed to load program: Permission denied
btf_vmlinux is malformed
Unrecognized arg#0 type PTR
; int crc32(struct pt_regs *ctx) {
0: (b7) r8 = 0
; char str[256] = {};
1: (7b) *(u64 *)(r10 -8) = r8
last_idx 1 first_idx 0
regs=100 stack=0 before 0: (b7) r8 = 0
2: (7b) *(u64 *)(r10 -16) = r8
3: (7b) *(u64 *)(r10 -24) = r8
4: (7b) *(u64 *)(r10 -32) = r8
5: (7b) *(u64 *)(r10 -40) = r8
6: (7b) *(u64 *)(r10 -48) = r8
7: (7b) *(u64 *)(r10 -56) = r8
8: (7b) *(u64 *)(r10 -64) = r8
9: (7b) *(u64 *)(r10 -72) = r8
10: (7b) *(u64 *)(r10 -80) = r8
11: (7b) *(u64 *)(r10 -88) = r8
12: (7b) *(u64 *)(r10 -96) = r8
13: (7b) *(u64 *)(r10 -104) = r8
14: (7b) *(u64 *)(r10 -112) = r8
15: (7b) *(u64 *)(r10 -120) = r8
16: (7b) *(u64 *)(r10 -128) = r8
17: (7b) *(u64 *)(r10 -136) = r8
18: (7b) *(u64 *)(r10 -144) = r8
19: (7b) *(u64 *)(r10 -152) = r8
20: (7b) *(u64 *)(r10 -160) = r8
21: (7b) *(u64 *)(r10 -168) = r8
22: (7b) *(u64 *)(r10 -176) = r8
23: (7b) *(u64 *)(r10 -184) = r8
24: (7b) *(u64 *)(r10 -192) = r8
25: (7b) *(u64 *)(r10 -200) = r8
26: (7b) *(u64 *)(r10 -208) = r8
27: (7b) *(u64 *)(r10 -216) = r8
28: (7b) *(u64 *)(r10 -224) = r8
29: (7b) *(u64 *)(r10 -232) = r8
30: (7b) *(u64 *)(r10 -240) = r8
31: (7b) *(u64 *)(r10 -248) = r8
32: (7b) *(u64 *)(r10 -256) = r8
; bpf_probe_read(&str, sizeof(str), (void *)PT_REGS_RC(ctx));
33: (79) r3 = *(u64 *)(r1 +0)
34: (bf) r1 = r10
; 
35: (07) r1 += -256
; bpf_probe_read(&str, sizeof(str), (void *)PT_REGS_RC(ctx));
36: (b7) r2 = 256
37: (85) call bpf_probe_read#4
last_idx 37 first_idx 0
regs=4 stack=0 before 36: (b7) r2 = 256
38: (18) r7 = 0xffffffff
40: (18) r9 = 0xffffff00
; u64 startTime = bpf_ktime_get_ns();
42: (85) call bpf_ktime_get_ns#5
43: (7b) *(u64 *)(r10 -304) = r0
44: (18) r1 = 0xfffffffe
46: (18) r2 = 0xedb88320
; crc ^= *current++;
48: (71) r3 = *(u8 *)(r8 +0)
R8 invalid mem access 'inv'
processed 45 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1
> 
> HINT: The invalid mem access 'inv' error can happen if you try to
> dereference memory without first using bpf_probe_read() to copy it to
> the BPF stack. Sometimes the bpf_probe_read is automatic by the bcc
> rewriter, other times you'll need to be explicit.

提示:如果您尝试取消引用内存而不先使用 bpf_probe_read() 将其复制到 BPF 堆栈,则可能会发生无效内存访问 'inv' 错误。有时 bpf_probe_read 由密件抄送重写器自动生成,其他时候您需要明确说明。

Traceback (most recent call last):
  File "/home/pi/Desktop/crc32.py", line 116, in <module>
    b.attach_uretprobe(name="/bin/bash", sym="readline", fn_name="crc32")
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 1058, in attach_uretprobe
    fn = self.load_func(fn_name, BPF.KPROBE)
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 394, in load_func
    raise Exception("Failed to load BPF program %s: %s" %
Exception: Failed to load BPF program b'crc32': Permission denied

根据验证者的日志,您在此处有一些无效访问:

; crc ^= *current++;
48: (71) r3 = *(u8 *)(r8 +0)
R8 invalid mem access 'inv'

这可能是由于您的指针在 0 处初始化(指针本身,而不是它指向的值!),然后在没有初始化其内容的情况下尝试取消引用它(这不会无论如何,空指针都是不可能的)。

unsigned char* current = 0;  // current is 0

[...]
while (maxVal--) {
    crc ^= *current++;       // read at address 0 and increment this value??
    ...
}

为什么不对 current 使用常规变量而不是指针?