Re: __builtin_memcpy behavior


Toke Høiland-Jørgensen
 

"Tristan Mayfield" <mayfieldtristan@...> writes:

I'm not sure where the memory it was reading was and if that should be
defined behavior, but I thought I would send this here and see if this
is intended or if I have actually found something unexpected.
bpf_probe_read() will happily read any piece of kernel memory, it
doesn't respect kernel boundaries. So if the call succeeded (you did
check the return code, right?), that just means that the memory it was
reading contained *something*, not that it was actually what you were
*expecting* it to be.

Should __builtin_memcpy be used? Or should bpf_probe_read? If
bpf_probe_read is recommended, is there a way we can verify that we're
not reading garbage data in this context other than having a human
eyeball the data returned? Or is that just a necessary part of BPF
development in this context? Is this issue something that the verifier
can even check at load time? I can provide more information on the
program and/or bug if it's needed, thanks!
In this case, I think what you're after is the BPF CO-RE facility in
general. Have a look at Andrii's excellent introduction post here:
https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html

But basically, what it means is that if you add a magic attribute
(preserve_access_index) to your variables, libbpf will notice that and
perform load-time relocations so you get the right offset on the kernel
you're running on. You can do this with your self-defined struct, but
with BTF you don't even have to do that: You can make bpftool spit out a
header file with all the structs defined by the current kernel and just
include that (the struct name in this case would be 'struct
trace_event_raw_tcp_event_sk_skb'). To do this, issue:

bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

and use that as an include file. bpftool will even add a nice pragma
statement at the top of the file so that all structs defined in it will
automatically get the preserve_access_index attribute; which means you
can basically use them like regular struct members (i.e., you can stick
with __builtin_memcpy() and regular assignments) and still get the magic
CO-RE relocations on load.

Note that all this requires that your libbpf and clang versions are
recent enough to understand all this, and libbpf will need the kernel
BTF information to be present at load time (check for the existence of
/sys/kernel/btf/vmlinux on the target system).

-Toke

Join iovisor-dev@lists.iovisor.org to automatically receive all group messages.