ebpf icon indicating copy to clipboard operation
ebpf copied to clipboard

btf: CO-RE: types from (other) kmod BTF are not available

Open tpapagian opened this issue 1 year ago • 3 comments

cilium/ebpf can detect if a symbol is part of a kmod and load it automatically. This is done here by checking the function name that the user wants to attach in /proc/kallsyms.

This does not work as expected when we want to relocate a symbol that is part of a kmod but the attach functions is not.

As an example, in my system, overlay is build as a module, and its BTF resides in /sys/kernel/btf/overlay. The following program attaches to ovl_inode_lower, a function from overlay kmod. cilium/ebpf will check that and load overlay's BTF. This will also be used to evaluate bpf_core_type_exists(struct ovl_entry), the verifier will remove the infinite loop, and the program will load as expected.

SEC("fentry/ovl_inode_lower")
int BPF_PROG(ovl_inode_lower, struct inode *inode)
{
	if (!bpf_core_type_exists(struct ovl_entry))
		while(1) {}

	return 0;
}

On the other hand, the following program attaches to a function that is not part of any kmod. Thus cilium/ebpf will not load overlay's BTF. bpf_core_type_exists(struct ovl_entry) will evaluate to 0, the infinite loop will not be removed by the verifier and the program fails to load (even the kmod BTF exists).

SEC("fentry/security_file_open")
int BPF_PROG(security_file_open, struct file *file)
{
	if (!bpf_core_type_exists(struct ovl_entry))
		while(1) {}

	return 0;
}

These are tested with these programs with cilium/ebpf v0.15.0 and the output is:

$ sudo ./main
Program ovl_inode_lower loaded successfully

Failed to load program security_file_open with error:
 ebpf.NewProgram: load program: invalid argument:
	0: R1=ctx() R10=fp0
	; int BPF_PROG(security_file_open, struct file *file)
	0: (b7) r1 = 0                        ; R1_w=0
	; if (!bpf_core_type_exists(struct ovl_entry))
	1: (55) if r1 != 0x0 goto pc+1        ; R1_w=0
	; while(1) {}
	2: (05) goto pc-1
	2: (05) goto pc-1
	2: (05) goto pc-1
	2: (05) goto pc-1
	2: (05) goto pc-1
	2: (05) goto pc-1
	infinite loop detected at insn 2
	cur state: R1=0 R10=fp0
	old state: R1_w=0 R10=fp0
	processed 9 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 0

A way to overcome this limitation is to manually load the overlay BTF with a function similar to this one and provide its output to ProgramOptions.KernelTypes. This makes the second program to load as well.

tpapagian avatar Jul 11 '24 21:07 tpapagian