-
Notifications
You must be signed in to change notification settings - Fork 768
kfunc: poison all weak kfunc calls if the kernel lacks BTF #1774
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
The error is I think that makes sense if we think about it. Kernel modules use split BTF, they essentially extend the vmlinux the kernel ships with. Strings in the module BTF are encoded as I see two ways of approaching this. First, If we are in a situation where a custom BTF is provided, simply do not attempt to use the module BTF. If the user needs type from a module, he has to make sure that the custom BTF contains the types from the module as well. Second, is we could allow users to provide a set of module BTFs which we would consult instead of the module BTFs from the kernel itself (if any exist). It would be up to the user to ensure they are generated with the provided vmlinux BTF as base. This can be sometime we add later as addition to the first approach. |
To add a data point to this discussion, BTFHub ships a single blob per kernel and seems to disregard kernel modules entirely. (I could be wrong, of course!) libbpf also accepts only a single blob in
Purely for doing CO-RE, all kmods could technically be merged into a single blob, but it doesn't seem like the btfhub tooling currently supports that. And since these kernels aren't getting any younger, I doubt there's much incentive to do so. Can't find the source, but if |
I don't think it's possible to use external kmod BTF for kfuncs in the first place. See the code which adds the module handle to I forget how kfuncs targeting the kernel work exactly. Is it even possible without having BTF built in? AKA, not sure this change makes sense at all. |
Good points! I assume it may be possible to invoke vmlinux kfuncs using external BTF if a distro/admin decided to ship BTF separately instead of in /sys/kernel/btf as a 'security' measure? Iirc kfuncs are referred to by btf id. We probably shouldn't take kmod BTF into account during resolving in any case. |
Exactly, so how does the kernel figure out what to attach to if it doesn't have BTF included? It also needs to do the id -> kfunc lookup, no? And if it needs BTF included, why is it not available in /sys/kernel/btf? @bogushevich can you tell us a bit more when / how this is useful / necessary? |
ACK. From what I understand from the kconfigs and header files is that when compiling with BTF, the kfunc BTF ids are encoded in the ".BTF_ids" ELF section of the kernel, which are then read at runtime to know which ids are kfuncs with what flags. If you don't compile the kernel with BTF, these are not included, thus no kfuncs. Even if you were to create BTF from the DWARF like those on BTFHub. |
@bogushevich how about we document this on fixupKfuncs so that future generations don't go down the same rabbit hole? |
Sorry, it was my mistake. You are right, after this commit my program is loaded successfully, but doesn't work properly. volatile const __u8 conntrack_enabled = 0;
extern struct nf_conn *bpf_skb_ct_lookup(
struct __sk_buff *,
struct bpf_sock_tuple *, u32,
struct bpf_ct_opts___local *, u32
) __ksym __weak;
if (conntrack_enabled) {
struct nf_conn *ct = bpf_skb_ct_lookup(/*...*/)
if (ct) {/*...*/}
} So if flag conntrack_enabled is not set from user space, program is successfully loaded even on kernels that don’t support necessary kfuncs. But if there is no system BTF, program fallback to custom BTF and loading is failed on fixupKfuncs step regardless of flag value. |
I think this makes a lot of sense to support. @dylandreimerink @lmb Should we treat an error from |
I think so. I suggest we tolerate the
|
In order to enable portably running a single BPF object with kfuncs on kernels with and without BTF, fixupKfuncs needs to tolerate BTF not being available. This commit poisons all kfunc calls if (a) they were marked weak and (b) kernel BTF is not available. When guarded with the appropriate CO-RE conditions, this should make it possible to run BPF objects with kfunc calls on kernels without BTF. Signed-off-by: Timo Beckers <timo@isovalent.com> Reported-by: Maxim Bogushevich <boga1@mail.ru>
2a587ab
to
d9170bd
Compare
KFuncs fixing up loads only system BTF, so using custom (non-system) BTF specification with KFuncs leads to errors.