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);
        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),
        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))
        }
 
        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;
        }
        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",
        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;