Lets disasm jit code from this spyware:
[8] prog 0xffffb02dc0133000 id 160 len 46 jited_len 215 aux 0xffff8ccb58fab400 used_maps 1 used_btf 0 func_cnt 0
tag: 0F 86 19 76 BC 37 68 B3
stack_depth: 16
num_exentries: 0
type: 2 BPF_PROG_TYPE_KPROBE
expected_attach_type: 0 BPF_CGROUP_INET_INGRESS
used maps:
[0] 0xffff8ccbc1b1c600 - rb
...
ffffffffc07bc801 e80a38e6f1 call 0xffffffffb2620010 ; bpf_ringbuf_submit
ffffffffc07bc806 31c0 xor eax, eax
ffffffffc07bc808 415e pop r14
ffffffffc07bc80a 415d pop r13
ffffffffc07bc80c 5b pop rbx
ffffffffc07bc80d c9 leave
ffffffffc07bc80e c3 ret
and in ebpf opcodes:
43 85 00 00 00 C0 CF 02 00 call 0x2CFC0 ; bpf_ringbuf_submit
44 B7 00 00 00 00 00 00 00 mov r0, 0
45 95 00 00 00 00 00 00 00 ret
Here 0x2CFC0 is offset to bpf_ringbuf_submit from __bpf_call_base
The last call submit some data to bpf map rb with type BPF_MAP_TYPE_RINGBUF. If we could patch this function no data will be passed to usermode. How are these native function addresses filled in at all?Long story short - they are filled by bpf verifiers. It`s really madness how complex this logic is: they have array of bpf_verifier_ops for each type of bpf programs where function pointer get_func_proto returns structure bpf_func_proto which contains address of some function for binding.
I write simple PoC to patch address of function inside bpf_ringbuf_submit_proto to some retn instruction. Lets look again at jit code (sure you first need to load my driver and then run pamspy):
ffffffffc087ff99 e84704daf1 call 0xffffffffb26203e5 ; ptr to c3 byte
ffffffffc087ff9e 31c0 xor eax, eax
ffffffffc087ffa0 415e pop r14
ffffffffc087ffa2 415d pop r13
ffffffffc087ffa4 5b pop rbx
ffffffffc087ffa5 c9 leave
ffffffffc087ffa6 c3 ret
ebpf opcodes:
43 85 00 00 00 95 D3 02 00 call 0x2D395 ; FFFFFFFF812203E5
44 B7 00 00 00 00 00 00 00 mov r0, 0
45 95 00 00 00 00 00 00 00 ret
Lets see which artifacts from my driver we can find:
./lkmem -r -d -c -B -t -k kernel5.13 System.map
mem at 0xffffffffb36387a0 (bpf_ringbuf_submit_proto) patched to 0xffffffffb26203e5