linux/tools/lib/bpf
Runqing Yang d252a4a499 libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels
Background:
Libbpf automatically replaces calls to BPF bpf_probe_read_{kernel,user}
[_str]() helpers with bpf_probe_read[_str](), if libbpf detects that
kernel doesn't support new APIs. Specifically, libbpf invokes the
probe_kern_probe_read_kernel function to load a small eBPF program into
the kernel in which bpf_probe_read_kernel API is invoked and lets the
kernel checks whether the new API is valid. If the loading fails, libbpf
considers the new API invalid and replaces it with the old API.

static int probe_kern_probe_read_kernel(void)
{
	struct bpf_insn insns[] = {
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),	/* r1 = r10 (fp) */
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),	/* r1 += -8 */
		BPF_MOV64_IMM(BPF_REG_2, 8),		/* r2 = 8 */
		BPF_MOV64_IMM(BPF_REG_3, 0),		/* r3 = 0 */
		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_probe_read_kernel),
		BPF_EXIT_INSN(),
	};
	int fd, insn_cnt = ARRAY_SIZE(insns);

	fd = bpf_prog_load(BPF_PROG_TYPE_KPROBE, NULL,
                           "GPL", insns, insn_cnt, NULL);
	return probe_fd(fd);
}

Bug:
On older kernel versions [0], the kernel checks whether the version
number provided in the bpf syscall, matches the LINUX_VERSION_CODE.
If not matched, the bpf syscall fails. eBPF However, the
probe_kern_probe_read_kernel code does not set the kernel version
number provided to the bpf syscall, which causes the loading process
alwasys fails for old versions. It means that libbpf will replace the
new API with the old one even the kernel supports the new one.

Solution:
After a discussion in [1], the solution is using BPF_PROG_TYPE_TRACEPOINT
program type instead of BPF_PROG_TYPE_KPROBE because kernel does not
enfoce version check for tracepoint programs. I test the patch in old
kernels (4.18 and 4.19) and it works well.

  [0] https://elixir.bootlin.com/linux/v4.19/source/kernel/bpf/syscall.c#L1360
  [1] Closes: https://github.com/libbpf/libbpf/issues/473

Signed-off-by: Runqing Yang <rainkin1993@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20220409144928.27499-1-rainkin1993@gmail.com
2022-04-10 20:15:22 -07:00
..
.gitignore libbpf: Make libbpf_version.h non-auto-generated 2021-09-13 15:36:47 -07:00
bpf_core_read.h libbpf: Fix endianness detection in BPF_CORE_READ_BITFIELD_PROBED() 2021-10-25 20:39:41 -07:00
bpf_endian.h libbpf: Make bpf_endian co-exist with vmlinux.h 2020-07-01 09:06:12 +02:00
bpf_gen_internal.h Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next 2021-12-10 15:56:13 -08:00
bpf_helpers.h libbpf: deprecate legacy BPF map definitions 2022-01-20 21:19:05 -08:00
bpf_prog_linfo.c libbpf: Streamline error reporting for high-level APIs 2021-05-25 17:32:35 -07:00
bpf_tracing.h libbpf: Add ARC support to bpf_tracing.h 2022-04-10 18:53:37 -07:00
bpf.c libbpf: Add bpf_link_create support for multi kprobes 2022-03-17 20:17:19 -07:00
bpf.h libbpf: Add bpf_link_create support for multi kprobes 2022-03-17 20:17:19 -07:00
btf_dump.c libbpf: Skip forward declaration when counting duplicated type names 2022-03-01 13:40:57 +01:00
btf.c libbpf: Don't return -EINVAL if hdr_len < offsetofend(core_relo_len) 2022-04-03 19:56:01 -07:00
btf.h libbpf: Deprecate forgotten btf__get_map_kv_tids() 2022-02-04 01:07:16 +01:00
Build libbpf: Wire up USDT API and bpf_link integration 2022-04-05 13:16:07 -07:00
gen_loader.c libbpf: Prepare light skeleton for the kernel. 2022-02-10 23:31:51 +01:00
hashmap.c libbpf: Use IS_ERR_OR_NULL() in hashmap__free() 2022-01-12 17:01:36 -08:00
hashmap.h libbpf, hashmap: Fix undefined behavior in hash_bits 2020-11-02 23:33:51 +01:00
libbpf_common.h libbpf: Deprecate bpf_prog_load_xattr() API 2021-12-02 15:23:41 -08:00
libbpf_errno.c libbpf: Streamline error reporting for high-level APIs 2021-05-25 17:32:35 -07:00
libbpf_internal.h libbpf: Improve library identification for uprobe binary path resolution 2022-04-07 11:42:50 -07:00
libbpf_legacy.h libbpf: .text routines are subprograms in strict mode 2022-03-17 23:11:15 -07:00
libbpf_probes.c libbpf: Improve LINUX_VERSION_CODE detection 2021-12-28 19:20:31 -08:00
libbpf_version.h libbpf: Support custom SEC() handlers 2022-03-05 09:38:15 -08:00
libbpf.c libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels 2022-04-10 20:15:22 -07:00
libbpf.h libbpf: Wire up USDT API and bpf_link integration 2022-04-05 13:16:07 -07:00
libbpf.map libbpf: Wire up USDT API and bpf_link integration 2022-04-05 13:16:07 -07:00
libbpf.pc.template libbpf: Add zlib as a dependency in pkg-config template 2019-12-16 14:55:29 -08:00
linker.c libbpf: Fix using invalidated memory in bpf_linker 2021-11-26 00:15:03 +01:00
Makefile Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next 2022-04-08 17:07:29 -07:00
netlink.c libbpf: Fix memleak in libbpf_netlink_recv() 2022-02-17 16:09:07 +01:00
nlattr.c libbpf: Switch to void * casting in netlink helpers 2021-06-22 17:04:02 +02:00
nlattr.h libbpf: Switch to void * casting in netlink helpers 2021-06-22 17:04:02 +02:00
relo_core.c libbpf: Split bpf_core_apply_relo() 2022-02-16 10:05:42 -08:00
relo_core.h libbpf: Split bpf_core_apply_relo() 2022-02-16 10:05:42 -08:00
ringbuf.c libbpf: Streamline error reporting for high-level APIs 2021-05-25 17:32:35 -07:00
skel_internal.h libbpf: Prepare light skeleton for the kernel. 2022-02-10 23:31:51 +01:00
str_error.c libbpf: Poison kernel-only integer types 2020-01-10 10:38:00 -08:00
str_error.h
strset.c libbpf: Fix memory leak in strset 2021-10-01 22:54:38 +02:00
strset.h libbpf: Extract internal set-of-strings datastructure APIs 2021-03-18 16:14:22 -07:00
usdt.bpf.h libbpf: Use weak hidden modifier for USDT BPF-side API functions 2022-04-08 22:24:15 +02:00
usdt.c libbpf: Use strlcpy() in path resolution fallback logic 2022-04-08 09:16:09 -07:00
xsk.c libbpf: Fix array_size.cocci warning 2022-03-07 22:13:00 -08:00
xsk.h libbpf: Deprecate AF_XDP support 2021-11-01 18:12:44 -07:00