iovisor / iovisor/bcc

tcptop doesn't work on aarch64

Open
#2,827 7 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
22.7k
Forks
4.1k
Avg merge
10d 4h
Merged PRs (30d)
3

Description

When trying to run tcptop on aarch64, I get the following error:
# /usr/share/bcc/tools/tcptop
bpf: Failed to load program: Permission denied
; struct sock *sk = ctx->regs[0]; int copied = ctx->regs[1];
0: (79) r8 = *(u64 *)(r1 +8)
; struct sock *sk = ctx->regs[0]; int copied = ctx->regs[1];
1: (79) r6 = *(u64 *)(r1 +0)
; u32 pid = bpf_get_current_pid_tgid() >> 32;
2: (85) call bpf_get_current_pid_tgid#14
3: (bf) r7 = r0
4: (b7) r1 = 0
; u16 dport = 0, family = ({ typeof(unsigned short) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_family); _val; });
5: (6b) *(u16 *)(r10 -48) = r1
last_idx 5 first_idx 0
regs=2 stack=0 before 4: (b7) r1 = 0
; u16 dport = 0, family = ({ typeof(unsigned short) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_family); _val; });
6: (bf) r3 = r6
7: (07) r3 += 16
8: (bf) r1 = r10
;
9: (07) r1 += -48
; u16 dport = 0, family = ({ typeof(unsigned short) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_family); _val; });
10: (b7) r2 = 2
11: (85) call bpf_probe_read#4
last_idx 11 first_idx 0
regs=4 stack=0 before 10: (b7) r2 = 2
; struct sock *sk = ctx->regs[0]; int copied = ctx->regs[1];
12: (bf) r1 = r8
13: (67) r1 <<= 32
14: (c7) r1 s>>= 32
15: (b7) r2 = 1
; if (copied <= 0)
16: (6d) if r2 s> r1 goto pc+145
R0=inv(id=0) R1_w=inv(id=0,umin_value=1,umax_value=2147483647,var_off=(0x0; 0x7fffffff)) R2_w=inv1 R6=inv(id=0) R7=inv(id=0) R8=inv(id=0) R10=fp0 fp-48=??????mm
;
17: (77) r7 >>= 32
18: (69) r1 = *(u16 *)(r10 -48)
; if (family == AF_INET) {
19: (15) if r1 == 0xa goto pc+57
R0=inv(id=0) R1_w=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R2_w=inv1 R6=inv(id=0) R7_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8=inv(id=0) R10=fp0 fp-48=??????mm
20: (55) if r1 != 0x2 goto pc+141
R0=inv(id=0) R1=inv2 R2=inv1 R6=inv(id=0) R7=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8=inv(id=0) R10=fp0 fp-48=??????mm
21: (b7) r1 = 0
; ipv4_key.saddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_rcv_saddr); _val; });
22: (63) *(u32 *)(r10 -48) = r1
last_idx 22 first_idx 20
regs=2 stack=0 before 21: (b7) r1 = 0
23: (b7) r9 = 0
; ipv4_key.saddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_rcv_saddr); _val; });
24: (bf) r3 = r6
25: (07) r3 += 4
26: (bf) r1 = r10
;
27: (07) r1 += -48
; ipv4_key.saddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_rcv_saddr); _val; });
28: (b7) r2 = 4
29: (85) call bpf_probe_read#4
last_idx 29 first_idx 20
regs=4 stack=0 before 28: (b7) r2 = 4
; ipv4_key.saddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_rcv_saddr); _val; });
30: (61) r1 = *(u32 *)(r10 -48)
; ipv4_key.daddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_daddr); _val; });
31: (7b) *(u64 *)(r10 -112) = r1
32: (63) *(u32 *)(r10 -48) = r9
last_idx 32 first_idx 30
regs=200 stack=0 before 31: (7b) *(u64 *)(r10 -112) = r1
regs=200 stack=0 before 30: (61) r1 = *(u32 *)(r10 -48)
R0_w=inv(id=0) R6=inv(id=0) R7=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8=inv(id=0) R9_rw=invP0 R10=fp0 fp-48_r=????mmmm
parent didn't have regs=200 stack=0 marks
last_idx 29 first_idx 20
regs=200 stack=0 before 29: (85) call bpf_probe_read#4
regs=200 stack=0 before 28: (b7) r2 = 4
regs=200 stack=0 before 27: (07) r1 += -48
regs=200 stack=0 before 26: (bf) r1 = r10
regs=200 stack=0 before 25: (07) r3 += 4
regs=200 stack=0 before 24: (bf) r3 = r6
regs=200 stack=0 before 23: (b7) r9 = 0
33: (bf) r1 = r10
;
34: (07) r1 += -48
; ipv4_key.daddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_daddr); _val; });
35: (b7) r2 = 4
36: (bf) r3 = r6
37: (85) call bpf_probe_read#4
last_idx 37 first_idx 30
regs=4 stack=0 before 36: (bf) r3 = r6
regs=4 stack=0 before 35: (b7) r2 = 4
; ipv4_key.daddr = ({ typeof(__be32) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_daddr); _val; });
38: (61) r1 = *(u32 *)(r10 -48)
; ipv4_key.lport = ({ typeof(__u16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_num); _val; });
39: (7b) *(u64 *)(r10 -120) = r1
40: (6b) *(u16 *)(r10 -48) = r9
; ipv4_key.lport = ({ typeof(__u16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_num); _val; });
41: (bf) r3 = r6
42: (07) r3 += 14
43: (bf) r1 = r10
;
44: (07) r1 += -48
; ipv4_key.lport = ({ typeof(__u16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_num); _val; });
45: (b7) r2 = 2
46: (85) call bpf_probe_read#4
last_idx 46 first_idx 30
regs=4 stack=0 before 45: (b7) r2 = 2
; ipv4_key.lport = ({ typeof(__u16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_num); _val; });
47: (69) r9 = *(u16 *)(r10 -48)
; dport = ({ typeof(__be16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_dport); _val; });
48: (b7) r1 = 0
49: (6b) *(u16 *)(r10 -48) = r1
last_idx 49 first_idx 47
regs=2 stack=0 before 48: (b7) r1 = 0
; ipv4_key.lport = ({ typeof(__u16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_num); _val; });
50: (07) r6 += 12
51: (bf) r1 = r10
;
52: (07) r1 += -48
; dport = ({ typeof(__be16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_dport); _val; });
53: (b7) r2 = 2
54: (bf) r3 = r6
55: (85) call bpf_probe_read#4
last_idx 55 first_idx 47
regs=4 stack=0 before 54: (bf) r3 = r6
regs=4 stack=0 before 53: (b7) r2 = 2
; dport = ({ typeof(__be16) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val), (u64)&sk->__sk_common.skc_dport); _val; });
56: (69) r1 = *(u16 *)(r10 -48)
; ipv4_key.dport = ntohs(dport);
57: (dc) r1 = be16 r1
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
58: (6b) *(u16 *)(r10 -34) = r1
59: (6b) *(u16 *)(r10 -36) = r9
60: (79) r1 = *(u64 *)(r10 -120)
61: (63) *(u32 *)(r10 -40) = r1
62: (79) r1 = *(u64 *)(r10 -112)
63: (63) *(u32 *)(r10 -44) = r1
64: (63) *(u32 *)(r10 -48) = r7
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
65: (18) r1 = 0xffffd26fc3ea6c00
67: (bf) r2 = r10
;
68: (07) r2 += -48
; return bpf_map_lookup_elem((void *)map, key);
69: (85) call bpf_map_lookup_elem#1
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
70: (15) if r0 == 0x0 goto pc+70
R0=map_value(id=0,off=0,ks=16,vs=8,imm=0) R6=inv(id=0) R7=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8=inv(id=0) R9=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0 fp-40=mmmmmmmm fp-48=mmmmmmmm fp-112=mmmmmmmm fp-120=mmmmmmmm
;
71: (67) r8 <<= 32
72: (c7) r8 s>>= 32
73: (79) r1 = *(u64 *)(r0 +0)
R0=map_value(id=0,off=0,ks=16,vs=8,imm=0) R6=inv(id=0) R7=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8_w=inv(id=0,smin_value=-2147483648,smax_value=2147483647) R9=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0 fp-40=mmmmmmmm fp-48=mmmmmmmm fp-112=mmmmmmmm fp-120=mmmmmmmm
74: (0f) r1 += r8
75: (7b) *(u64 *)(r0 +0) = r1
R0=map_value(id=0,off=0,ks=16,vs=8,imm=0) R1_w=inv(id=0) R6=inv(id=0) R7=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8_w=inv(id=0,smin_value=-2147483648,smax_value=2147483647) R9=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0 fp-40=mmmmmmmm fp-48=mmmmmmmm fp-112=mmmmmmmm fp-120=mmmmmmmm
76: (05) goto pc+85
; }
162: (b7) r0 = 0
163: (95) exit

from 70 to 141: R0=inv0 R6=inv(id=0) R7=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8=inv(id=0) R9=inv(id=0,umax_value=65535,var_off=(0x0; 0xffff)) R10=fp0 fp-40=mmmmmmmm fp-48=mmmmmmmm fp-112=mmmmmmmm fp-120=mmmmmmmm
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
141: (67) r8 <<= 32
142: (c7) r8 s>>= 32
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
143: (7b) *(u64 *)(r10 -96) = r8
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
144: (18) r1 = 0xffffd26fc3ea6c00
146: (bf) r2 = r10
; ({ typeof(ipv4_recv_bytes.key) _key = ipv4_key; typeof(ipv4_recv_bytes.leaf) *_leaf = bpf_map_lookup_elem_(bpf_pseudo_fd(1, -2), &_key); if (_leaf) (*_leaf) += copied;else { typeof(ipv4_recv_bytes.leaf) _zleaf; __builtin_memset(&_zleaf, 0, sizeof(_zleaf)); _zleaf += copied;bpf_map_update_elem_(bpf_pseudo_fd(1, -2), &_key, &_zleaf, BPF_NOEXIST); } });
147: (07) r2 += -48
148: (bf) r3 = r10
149: (07) r3 += -96
150: (05) goto pc+9
;
160: (b7) r4 = 1
161: (85) call bpf_map_update_elem#2
; }
162: (b7) r0 = 0
163: (95) exit

from 20 to 162: safe

from 19 to 77: R0=inv(id=0) R1_w=inv10 R2_w=inv1 R6=inv(id=0) R7_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R8=inv(id=0) R10=fp0 fp-48=??????mm
;
77: (b7) r9 = 0
; struct ipv6_key_t ipv6_key = {.pid = pid};
78: (7b) *(u64 *)(r10 -48) = r9
last_idx 78 first_idx 12
regs=200 stack=0 before 77: (b7) r9 = 0
; struct ipv6_key_t ipv6_key = {.pid = pid};
79: (63) *(u32 *)(r10 -48) = r7
; struct ipv6_key_t ipv6_key = {.pid = pid};
80: (7b) *(u64 *)(r10 +8) = r9
invalid stack off=8 size=8
processed 96 insns (limit 1000000) max_states_per_insn 0 total_states 7 peak_states 7 mark_read 4

Traceback (most recent call last):
File "/usr/share/bcc/tools/tcptop", line 230, in
b = BPF(text=bpf_text)
File "/usr/lib/python3.8/site-packages/bcc/__init__.py", line 364, in __init__
self._trace_autoload()
File "/usr/lib/python3.8/site-packages/bcc/__init__.py", line 1178, in _trace_autoload
fn = self.load_func(func_name, BPF.KPROBE)
File "/usr/lib/python3.8/site-packages/bcc/__init__.py", line 403, in load_func
raise Exception("Failed to load BPF program %s: %s" %
Exception: Failed to load BPF program b'kprobe__tcp_cleanup_rbuf': Permission denied

It seems to be related to alignemnent in the ipv6_key_t structure. When moving the 32 bits pid field after the two 128 bits address fields, tcptop seems to works. I'm not sure that's a proper fix though.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with /usr/share/bcc/tools/tcptop and the BPF text passed to BPF(text=bpf_text) near the reported IPv6-key stack write. Reproduce the verifier failure on aarch64 and determine the relevant constraint from the log; done means tcptop loads and runs successfully on that architecture.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux, python
Domain
networking, observability-sre, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.