-
Notifications
You must be signed in to change notification settings - Fork 768
Description
While looking at __weak
support I came across the following pattern used in selftests:
void invalid_kfunc(void) __ksym __weak;
#define bpf_ksym_exists(sym) \
({ \
_Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak"); \
!!sym; \
})
SEC("xdp") int xdp_prog(struct xdp_md *ctx) {
if (bpf_ksym_exists(invalid_kfunc))
invalid_kfunc();
return 0;
}
So, essentially, this allows programs to handle cases where a given kfunc isn't available such as on older kernels or on kernels missing certain KCONFIG.
The __weak
attribute is required for this to work so initially this results in a relocating instruction: asm relocation: invalid_kfunc: unsupported binding: STB_WEAK
error. But assuming this is resolved by #466. We get the error: fixing up kfuncs: kfunc "invalid_kfunc": not supported
.
The instructions for the example program are:
xdp_prog:
; if (bpf_ksym_exists(invalid_kfunc))
0: LdImmDW dst: r1 imm: 0 <invalid_kfunc>
2: JEqImm dst: r1 off: 1 imm: 0
; invalid_kfunc();
3: Call Kfunc(-1) <invalid_kfunc>
; return 0;
4: MovImm dst: r0 imm: 0
5: Exit
The way libbpf handles this is by simply doing nothing. Since instruction 0 has a imm of 0 by default the code branch with the call is dead code and never trips the verifier.
There is a secondary issue, that being that we only relocate Call
instructions, even if the kfunc were valid, instruction 0 would be ignored. So if we can fix both, we effectively allow CO-RE with kfuncs.