On 12/8/22 6:57 PM, Stanislav Fomichev wrote:
On Thu, Dec 8, 2022 at 4:07 PM Toke Høiland-Jørgensen <toke@xxxxxxxxxx> wrote:
Stanislav Fomichev <sdf@xxxxxxxxxx> writes:
Another UX thing I ran into is that libbpf will bail out if it can't
find the kfunc in the kernel vmlinux, even if the code calling the
function is behind an always-false if statement (which would be
eliminated as dead code from the verifier). This makes it a bit hard to
conditionally use them. Should libbpf just allow the load without
performing the relocation (and let the verifier worry about it), or
should we have a bpf_core_kfunc_exists() macro to use for checking?
Maybe both?
I'm not sure how libbpf can allow the load without performing the
relocation; maybe I'm missing something.
IIUC, libbpf uses the kfunc name (from the relocation?) and replaces
it with the kfunc id, right?
Yeah, so if it can't find the kfunc in vmlinux, just write an id of 0.
This will trip the check at the top of fixup_kfunc_call() in the
verifier, but if the code is hidden behind an always-false branch (an
rodata variable set to zero, say) the instructions should get eliminated
before they reach that point. That way you can at least turn it off at
runtime (after having done some kind of feature detection) without
having to compile it out of your program entirely.
Having bpf_core_kfunc_exists would help, but this probably needs
compiler work first to preserve some of the kfunc traces in vmlinux.h?
hmm.... if I follow correctly, it wants the libbpf to accept a bpf prog using a
kfunc that does not exist in the running kernel?
Have you tried "__weak":
extern void dummy_kfunc(void) __ksym __weak;
SEC("tc")
int load(struct __sk_buff *skb)
{
if (dummy_kfunc) {
dummy_kfunc();
return TC_ACT_SHOT;
}
return TC_ACT_UNSPEC;
}