libbpf: Fix kernel BTF detection logic
authorMauricio Vásquez <mauricio@kinvolk.io>
Thu, 13 Jan 2022 19:39:33 +0000 (14:39 -0500)
committeryonghong-song <ys114321@gmail.com>
Fri, 14 Jan 2022 16:10:53 +0000 (08:10 -0800)
bpf_has_kernel_btf() is used to check whether the kernel has BTF or not.
It's part of the logic that checks if kfunc and lsm programs are supported.
Before this commit it used libbpf_find_vmlinux_btf_id(), this function
calls btf__load_vmlinux_btf() that tries to load the BTF from different
places, the canonical vmlinux in sysfs and other locations.

This is not accurate as kfunc and lsm programs require to have the BTF
file exposed directly by the kernel (CONFIG_DEBUG_INFO_BTF should be set).
This commit updates that function to check if BTF is exposed directly
by the kernel.

This was causing opensnoop to try to use kfunc programs (instead of
kprobes) in systems where they are not supported:

$ ls /usr/lib/debug/boot/vmlinux-$(uname -r)
/usr/lib/debug/boot/vmlinux-5.11.0-38-generic

$ cat /boot/config-$(uname -r) | grep -i CONFIG_DEBUG_INFO_BTF
$ sudo stat /sys/kernel/btf/vmlinux
stat: cannot stat '/sys/kernel/btf/vmlinux': No such file or directory

$ sudo python3 /usr/share/bcc/tools/opensnoop
bpf: Failed to load program: Invalid argument

Traceback (most recent call last):
  File "/usr/share/bcc/tools/opensnoop", line 321, in <module>
    b = BPF(text=bpf_text)
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 483, in __init__
    self._trace_autoload()
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 1466, in _trace_autoload
    self.attach_kretfunc(fn_name=func_name)
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 1140, in attach_kretfunc
    fn = self.load_func(fn_name, BPF.TRACING)
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 522, in load_func
    raise Exception("Failed to load BPF program %s: %s" %
Exception: Failed to load BPF program b'kretfunc____x64_sys_open': Invalid argument

Fixes: 1ad2656a1d9c ("Add support_kfunc function to BPF object")

Signed-off-by: Mauricio Vásquez <mauricio@kinvolk.io>
src/cc/libbpf.c

index 63938eb..e640329 100644 (file)
@@ -1350,7 +1350,16 @@ int bpf_attach_raw_tracepoint(int progfd, const char *tp_name)
 
 bool bpf_has_kernel_btf(void)
 {
-  return libbpf_find_vmlinux_btf_id("bpf_prog_put", 0) > 0;
+  struct btf *btf;
+  int err;
+
+  btf = btf__parse_raw("/sys/kernel/btf/vmlinux");
+  err = libbpf_get_error(btf);
+  if (err)
+    return false;
+
+  btf__free(btf);
+  return true;
 }
 
 int kernel_struct_has_field(const char *struct_name, const char *field_name)