Lets dissect some typical ebpf spyware. It sets up uprobes on
- SSL_read_ex
- SSL_read
- SSL_write_ex
- SSL_write
- gotls_write_register
- gotls_read_register
- gotls_exit_read_register
and uses bpf functions probe_read_user& probe_read_user_str to steal data and map_update_elem& ringbuf_submit to store data in bpf maps
How we can mitigate this?
Official way is to use LSM - function __sys_bpf calls security_bpf so we could register with security_add_hooks LSM hook with index bpf. This effectively prevents loading of ebpf program and sometimes is not what we want - for example in case of honeypots there is high chance that usermode program just will exits after failed ebpf program loading and you can't monitor which connections it will try to establish
Another way - is to patch bpf_func_proto for selected functions, like I did. However this is brutal method and affects all ebpf programs (I still believe that some is not spyware, he-he)
Luckily there is way to blind only some types of ebpf programs - method get_func_proto in bpf_verifier_ops. I made PoC to blind aforementioned 4 functions for BPF_PROG_TYPE_TRACING & BPF_PROG_TYPE_KPROBE only
Now we have another problem - how to check integrity of bpf_verifier_ops? I've also add this check in my lkcd. Example of output when PoC ublind is loaded looks like:
[24] type BPF_PROG_TYPE_TRACING at 0xffffffffc1357720 - ublind!s_trace_patched
get_func_proto: 0xffffffffc13551e0 - ublind!my_func_proto
is_valid_access: 0xffffffffaee24e20 - kernel!tracing_prog_is_valid_access