Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'libbpf-clarify-raw-address-single-kprobe-attach-behavior'

Hoyeon Lee says:

====================
libbpf: clarify raw-address single kprobe attach behavior

Today libbpf documents single-kprobe attach through func_name, with an
optional offset. For the PMU-based path, func_name = NULL with an
absolute address in offset already works as well, but that is not
described in the API.

This patchset clarifies this behavior. First commit fixes kprobe
and uprobe attach error handling to use direct error codes. Next adds
kprobe API comments for the raw-address form and rejects it explicitly
for legacy tracefs/debugfs kprobes. Last adds PERF and LINK selftests
for the raw-address form, and checks that LEGACY rejects it.
---
Changes in v7:
- Change selftest line wrapping and assertions

Changes in v6:
- Split the kprobe/uprobe direct error-code fix into a separate patch

Changes in v5:
- Add kprobe API docs, use -EOPNOTSUPP, and switch selftests to LIBBPF_OPTS

Changes in v4:
- Inline raw-address error formatting and remove the probe_target buffer

Changes in v3:
- Drop bpf_kprobe_opts.addr and reuse offset when func_name is NULL
- Make legacy tracefs/debugfs kprobes reject the raw-address form
- Update selftests to cover PERF/LINK raw-address attach and LEGACY reject

Changes in v2:
- Fix line wrapping and indentation
====================

Link: https://patch.msgid.link/20260401143116.185049-1-hoyeon.lee@suse.com
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

+116 -9
+10 -8
tools/lib/bpf/libbpf.c
··· 11843 11843 default: 11844 11844 return libbpf_err_ptr(-EINVAL); 11845 11845 } 11846 + if (!func_name && legacy) 11847 + return libbpf_err_ptr(-EOPNOTSUPP); 11846 11848 11847 11849 if (!legacy) { 11848 11850 pfd = perf_event_open_probe(false /* uprobe */, retprobe, ··· 11864 11862 offset, -1 /* pid */); 11865 11863 } 11866 11864 if (pfd < 0) { 11867 - err = -errno; 11868 - pr_warn("prog '%s': failed to create %s '%s+0x%zx' perf event: %s\n", 11865 + err = pfd; 11866 + pr_warn("prog '%s': failed to create %s '%s%s0x%zx' perf event: %s\n", 11869 11867 prog->name, retprobe ? "kretprobe" : "kprobe", 11870 - func_name, offset, 11871 - errstr(err)); 11868 + func_name ?: "", func_name ? "+" : "", 11869 + offset, errstr(err)); 11872 11870 goto err_out; 11873 11871 } 11874 11872 link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts); 11875 11873 err = libbpf_get_error(link); 11876 11874 if (err) { 11877 11875 close(pfd); 11878 - pr_warn("prog '%s': failed to attach to %s '%s+0x%zx': %s\n", 11876 + pr_warn("prog '%s': failed to attach to %s '%s%s0x%zx': %s\n", 11879 11877 prog->name, retprobe ? "kretprobe" : "kprobe", 11880 - func_name, offset, 11881 - errstr(err)); 11878 + func_name ?: "", func_name ? "+" : "", 11879 + offset, errstr(err)); 11882 11880 goto err_clean_legacy; 11883 11881 } 11884 11882 if (legacy) { ··· 12854 12852 binary_path, func_offset, pid); 12855 12853 } 12856 12854 if (pfd < 0) { 12857 - err = -errno; 12855 + err = pfd; 12858 12856 pr_warn("prog '%s': failed to create %s '%s:0x%zx' perf event: %s\n", 12859 12857 prog->name, retprobe ? "uretprobe" : "uprobe", 12860 12858 binary_path, func_offset,
+26 -1
tools/lib/bpf/libbpf.h
··· 557 557 size_t sz; 558 558 /* custom user-provided value fetchable through bpf_get_attach_cookie() */ 559 559 __u64 bpf_cookie; 560 - /* function's offset to install kprobe to */ 560 + /* function offset, or raw address if func_name == NULL */ 561 561 size_t offset; 562 562 /* kprobe is return probe */ 563 563 bool retprobe; ··· 565 565 enum probe_attach_mode attach_mode; 566 566 size_t :0; 567 567 }; 568 + 568 569 #define bpf_kprobe_opts__last_field attach_mode 569 570 571 + /** 572 + * @brief **bpf_program__attach_kprobe()** attaches a BPF program to a 573 + * kernel function entry or return. 574 + * 575 + * @param prog BPF program to attach 576 + * @param retprobe Attach to function return 577 + * @param func_name Name of the kernel function to attach to 578 + * @return Reference to the newly created BPF link; or NULL is returned on 579 + * error, error code is stored in errno 580 + */ 570 581 LIBBPF_API struct bpf_link * 571 582 bpf_program__attach_kprobe(const struct bpf_program *prog, bool retprobe, 572 583 const char *func_name); 584 + 585 + /** 586 + * @brief **bpf_program__attach_kprobe_opts()** is just like 587 + * bpf_program__attach_kprobe() except with an options struct 588 + * for various configurations. 589 + * 590 + * @param prog BPF program to attach 591 + * @param func_name Name of the kernel function to attach to. If NULL, 592 + * opts->offset is treated as a raw kernel address. Raw-address attach 593 + * is supported with PROBE_ATTACH_MODE_PERF and PROBE_ATTACH_MODE_LINK. 594 + * @param opts Options for altering program attachment 595 + * @return Reference to the newly created BPF link; or NULL is returned on 596 + * error, error code is stored in errno 597 + */ 573 598 LIBBPF_API struct bpf_link * 574 599 bpf_program__attach_kprobe_opts(const struct bpf_program *prog, 575 600 const char *func_name,
+80
tools/testing/selftests/bpf/prog_tests/attach_probe.c
··· 123 123 test_attach_probe_manual__destroy(skel); 124 124 } 125 125 126 + /* manual attach address-based kprobe/kretprobe testings */ 127 + static void test_attach_kprobe_by_addr(enum probe_attach_mode attach_mode) 128 + { 129 + LIBBPF_OPTS(bpf_kprobe_opts, kprobe_opts); 130 + struct test_attach_probe_manual *skel; 131 + unsigned long func_addr; 132 + 133 + if (!ASSERT_OK(load_kallsyms(), "load_kallsyms")) 134 + return; 135 + 136 + func_addr = ksym_get_addr(SYS_NANOSLEEP_KPROBE_NAME); 137 + if (!ASSERT_NEQ(func_addr, 0UL, "func_addr")) 138 + return; 139 + 140 + skel = test_attach_probe_manual__open_and_load(); 141 + if (!ASSERT_OK_PTR(skel, "skel_kprobe_manual_open_and_load")) 142 + return; 143 + 144 + kprobe_opts.attach_mode = attach_mode; 145 + kprobe_opts.retprobe = false; 146 + kprobe_opts.offset = func_addr; 147 + skel->links.handle_kprobe = 148 + bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe, 149 + NULL, &kprobe_opts); 150 + if (!ASSERT_OK_PTR(skel->links.handle_kprobe, "attach_kprobe_by_addr")) 151 + goto cleanup; 152 + 153 + kprobe_opts.retprobe = true; 154 + skel->links.handle_kretprobe = 155 + bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe, 156 + NULL, &kprobe_opts); 157 + if (!ASSERT_OK_PTR(skel->links.handle_kretprobe, "attach_kretprobe_by_addr")) 158 + goto cleanup; 159 + 160 + /* trigger & validate kprobe && kretprobe */ 161 + usleep(1); 162 + 163 + ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res"); 164 + ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res"); 165 + 166 + cleanup: 167 + test_attach_probe_manual__destroy(skel); 168 + } 169 + 170 + /* reject legacy address-based kprobe attach */ 171 + static void test_attach_kprobe_legacy_by_addr_reject(void) 172 + { 173 + LIBBPF_OPTS(bpf_kprobe_opts, kprobe_opts); 174 + struct test_attach_probe_manual *skel; 175 + unsigned long func_addr; 176 + 177 + if (!ASSERT_OK(load_kallsyms(), "load_kallsyms")) 178 + return; 179 + 180 + func_addr = ksym_get_addr(SYS_NANOSLEEP_KPROBE_NAME); 181 + if (!ASSERT_NEQ(func_addr, 0UL, "func_addr")) 182 + return; 183 + 184 + skel = test_attach_probe_manual__open_and_load(); 185 + if (!ASSERT_OK_PTR(skel, "skel_kprobe_manual_open_and_load")) 186 + return; 187 + 188 + kprobe_opts.attach_mode = PROBE_ATTACH_MODE_LEGACY; 189 + kprobe_opts.offset = func_addr; 190 + skel->links.handle_kprobe = 191 + bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe, 192 + NULL, &kprobe_opts); 193 + ASSERT_ERR_PTR(skel->links.handle_kprobe, "attach_kprobe_legacy_by_addr"); 194 + ASSERT_EQ(libbpf_get_error(skel->links.handle_kprobe), 195 + -EOPNOTSUPP, "attach_kprobe_legacy_by_addr_err"); 196 + 197 + test_attach_probe_manual__destroy(skel); 198 + } 199 + 126 200 /* attach uprobe/uretprobe long event name testings */ 127 201 static void test_attach_uprobe_long_event_name(void) 128 202 { ··· 552 478 test_attach_probe_manual(PROBE_ATTACH_MODE_PERF); 553 479 if (test__start_subtest("manual-link")) 554 480 test_attach_probe_manual(PROBE_ATTACH_MODE_LINK); 481 + if (test__start_subtest("kprobe-perf-by-addr")) 482 + test_attach_kprobe_by_addr(PROBE_ATTACH_MODE_PERF); 483 + if (test__start_subtest("kprobe-link-by-addr")) 484 + test_attach_kprobe_by_addr(PROBE_ATTACH_MODE_LINK); 485 + if (test__start_subtest("kprobe-legacy-by-addr-reject")) 486 + test_attach_kprobe_legacy_by_addr_reject(); 555 487 556 488 if (test__start_subtest("auto")) 557 489 test_attach_probe_auto(skel);