libbpf: Add support for kprobe session attach
authorJiri Olsa <jolsa@kernel.org>
Tue, 30 Apr 2024 11:28:27 +0000 (13:28 +0200)
committerAndrii Nakryiko <andrii@kernel.org>
Tue, 30 Apr 2024 16:45:53 +0000 (09:45 -0700)
Adding support to attach program in kprobe session mode
with bpf_program__attach_kprobe_multi_opts function.

Adding session bool to bpf_kprobe_multi_opts struct that allows
to load and attach the bpf program via kprobe session.
the attachment to create kprobe multi session.

Also adding new program loader section that allows:
 SEC("kprobe.session/bpf_fentry_test*")

and loads/attaches kprobe program as kprobe session.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20240430112830.1184228-5-jolsa@kernel.org
tools/lib/bpf/bpf.c
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h

index c9f4e04f38febff4e82002191381a97e9cf550cb..466a29d8012498a9adb22db9c852f6557569efee 100644 (file)
@@ -766,6 +766,7 @@ int bpf_link_create(int prog_fd, int target_fd,
                        return libbpf_err(-EINVAL);
                break;
        case BPF_TRACE_KPROBE_MULTI:
+       case BPF_TRACE_KPROBE_SESSION:
                attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
                attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
                attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
index 898d5d34ecea32221a4fcf9466886c1cb27b348f..16dae279a9002a4b749e4f2286e302434b4d6dfe 100644 (file)
@@ -9273,6 +9273,7 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin
 static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
+static int attach_kprobe_session(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);
@@ -9289,6 +9290,7 @@ static const struct bpf_sec_def section_defs[] = {
        SEC_DEF("uretprobe.s+",         KPROBE, 0, SEC_SLEEPABLE, attach_uprobe),
        SEC_DEF("kprobe.multi+",        KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
        SEC_DEF("kretprobe.multi+",     KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
+       SEC_DEF("kprobe.session+",      KPROBE, BPF_TRACE_KPROBE_SESSION, SEC_NONE, attach_kprobe_session),
        SEC_DEF("uprobe.multi+",        KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
        SEC_DEF("uretprobe.multi+",     KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
        SEC_DEF("uprobe.multi.s+",      KPROBE, BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi),
@@ -11381,13 +11383,14 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
        struct kprobe_multi_resolve res = {
                .pattern = pattern,
        };
+       enum bpf_attach_type attach_type;
        struct bpf_link *link = NULL;
        char errmsg[STRERR_BUFSIZE];
        const unsigned long *addrs;
        int err, link_fd, prog_fd;
+       bool retprobe, session;
        const __u64 *cookies;
        const char **syms;
-       bool retprobe;
        size_t cnt;
 
        if (!OPTS_VALID(opts, bpf_kprobe_multi_opts))
@@ -11426,6 +11429,12 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
        }
 
        retprobe = OPTS_GET(opts, retprobe, false);
+       session  = OPTS_GET(opts, session, false);
+
+       if (retprobe && session)
+               return libbpf_err_ptr(-EINVAL);
+
+       attach_type = session ? BPF_TRACE_KPROBE_SESSION : BPF_TRACE_KPROBE_MULTI;
 
        lopts.kprobe_multi.syms = syms;
        lopts.kprobe_multi.addrs = addrs;
@@ -11440,7 +11449,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
        }
        link->detach = &bpf_link__detach_fd;
 
-       link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &lopts);
+       link_fd = bpf_link_create(prog_fd, 0, attach_type, &lopts);
        if (link_fd < 0) {
                err = -errno;
                pr_warn("prog '%s': failed to attach: %s\n",
@@ -11546,6 +11555,32 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
        return libbpf_get_error(*link);
 }
 
+static int attach_kprobe_session(const struct bpf_program *prog, long cookie,
+                                struct bpf_link **link)
+{
+       LIBBPF_OPTS(bpf_kprobe_multi_opts, opts, .session = true);
+       const char *spec;
+       char *pattern;
+       int n;
+
+       *link = NULL;
+
+       /* no auto-attach for SEC("kprobe.session") */
+       if (strcmp(prog->sec_name, "kprobe.session") == 0)
+               return 0;
+
+       spec = prog->sec_name + sizeof("kprobe.session/") - 1;
+       n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
+       if (n < 1) {
+               pr_warn("kprobe session pattern is invalid: %s\n", pattern);
+               return -EINVAL;
+       }
+
+       *link = bpf_program__attach_kprobe_multi_opts(prog, pattern, &opts);
+       free(pattern);
+       return *link ? 0 : -errno;
+}
+
 static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link)
 {
        char *probe_type = NULL, *binary_path = NULL, *func_name = NULL;
index 1333ae20ebe68b10bc466b03d6b7873db2b741a4..c3f77d9260feaea1181ea49f65e033af03490e34 100644 (file)
@@ -539,10 +539,12 @@ struct bpf_kprobe_multi_opts {
        size_t cnt;
        /* create return kprobes */
        bool retprobe;
+       /* create session kprobes */
+       bool session;
        size_t :0;
 };
 
-#define bpf_kprobe_multi_opts__last_field retprobe
+#define bpf_kprobe_multi_opts__last_field session
 
 LIBBPF_API struct bpf_link *
 bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,