ebpf icon indicating copy to clipboard operation
ebpf copied to clipboard

loader: handle missing kfunc gracefully

Open dylandreimerink opened this issue 1 year ago • 0 comments

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.

dylandreimerink avatar Feb 20 '24 19:02 dylandreimerink