bpf, x86: Attach a cookie to fentry/fexit/fmod_ret/lsm.
authorKui-Feng Lee <kuifeng@fb.com>
Tue, 10 May 2022 20:59:21 +0000 (13:59 -0700)
committerAndrii Nakryiko <andrii@kernel.org>
Wed, 11 May 2022 04:58:31 +0000 (21:58 -0700)
Pass a cookie along with BPF_LINK_CREATE requests.

Add a bpf_cookie field to struct bpf_tracing_link to attach a cookie.
The cookie of a bpf_tracing_link is available by calling
bpf_get_attach_cookie when running the BPF program of the attached
link.

The value of a cookie will be set at bpf_tramp_run_ctx by the
trampoline of the link.

Signed-off-by: Kui-Feng Lee <kuifeng@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20220510205923.3206889-4-kuifeng@fb.com
arch/x86/net/bpf_jit_comp.c
include/linux/bpf.h
include/uapi/linux/bpf.h
kernel/bpf/bpf_lsm.c
kernel/bpf/syscall.c
kernel/bpf/trampoline.c
kernel/trace/bpf_trace.c
tools/include/uapi/linux/bpf.h

index 1fbc5cf1c7a7c848654f8b1934722f18458ccfdd..a2b6d197c226942f6359b0b17cc0d25983098f11 100644 (file)
@@ -1769,9 +1769,10 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
        u8 *jmp_insn;
        int ctx_cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
        struct bpf_prog *p = l->link.prog;
+       u64 cookie = l->cookie;
 
-       /* mov rdi, 0 */
-       emit_mov_imm64(&prog, BPF_REG_1, 0, 0);
+       /* mov rdi, cookie */
+       emit_mov_imm64(&prog, BPF_REG_1, (long) cookie >> 32, (u32) (long) cookie);
 
        /* Prepare struct bpf_tramp_run_ctx.
         *
index 256fb802e58046960c51fbb61f0cf8cd18e39d70..aba7ded564365a9a6f7394a0eb483283e0ee69b8 100644 (file)
@@ -1102,6 +1102,7 @@ struct bpf_link_ops {
 struct bpf_tramp_link {
        struct bpf_link link;
        struct hlist_node tramp_hlist;
+       u64 cookie;
 };
 
 struct bpf_tracing_link {
index 3d032ea1b6a32723609ad78c99c1d14bf741c142..bc7f89948f5497009615696e49010c46698e62a4 100644 (file)
@@ -1490,6 +1490,15 @@ union bpf_attr {
                                __aligned_u64   addrs;
                                __aligned_u64   cookies;
                        } kprobe_multi;
+                       struct {
+                               /* this is overlaid with the target_btf_id above. */
+                               __u32           target_btf_id;
+                               /* black box user-provided value passed through
+                                * to BPF program at the execution time and
+                                * accessible through bpf_get_attach_cookie() BPF helper
+                                */
+                               __u64           cookie;
+                       } tracing;
                };
        } link_create;
 
index 064eccba641d781a4b6862de9bbe9d93b5e66184..c1351df9f7ee895fb84784150d92f32e7b1ad87b 100644 (file)
@@ -117,6 +117,21 @@ static const struct bpf_func_proto bpf_ima_file_hash_proto = {
        .allowed        = bpf_ima_inode_hash_allowed,
 };
 
+BPF_CALL_1(bpf_get_attach_cookie, void *, ctx)
+{
+       struct bpf_trace_run_ctx *run_ctx;
+
+       run_ctx = container_of(current->bpf_ctx, struct bpf_trace_run_ctx, run_ctx);
+       return run_ctx->bpf_cookie;
+}
+
+static const struct bpf_func_proto bpf_get_attach_cookie_proto = {
+       .func           = bpf_get_attach_cookie,
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+};
+
 static const struct bpf_func_proto *
 bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
@@ -141,6 +156,8 @@ bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return prog->aux->sleepable ? &bpf_ima_inode_hash_proto : NULL;
        case BPF_FUNC_ima_file_hash:
                return prog->aux->sleepable ? &bpf_ima_file_hash_proto : NULL;
+       case BPF_FUNC_get_attach_cookie:
+               return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto : NULL;
        default:
                return tracing_prog_func_proto(func_id, prog);
        }
index d48165fccf49a2e4fd6296f35d8544600143d869..72e53489165d31883e9ce8b13039fa102a5a8b6c 100644 (file)
@@ -2921,7 +2921,8 @@ static const struct bpf_link_ops bpf_tracing_link_lops = {
 
 static int bpf_tracing_prog_attach(struct bpf_prog *prog,
                                   int tgt_prog_fd,
-                                  u32 btf_id)
+                                  u32 btf_id,
+                                  u64 bpf_cookie)
 {
        struct bpf_link_primer link_primer;
        struct bpf_prog *tgt_prog = NULL;
@@ -2986,6 +2987,7 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog,
        bpf_link_init(&link->link.link, BPF_LINK_TYPE_TRACING,
                      &bpf_tracing_link_lops, prog);
        link->attach_type = prog->expected_attach_type;
+       link->link.cookie = bpf_cookie;
 
        mutex_lock(&prog->aux->dst_mutex);
 
@@ -3271,7 +3273,7 @@ static int bpf_raw_tp_link_attach(struct bpf_prog *prog,
                        tp_name = prog->aux->attach_func_name;
                        break;
                }
-               return bpf_tracing_prog_attach(prog, 0, 0);
+               return bpf_tracing_prog_attach(prog, 0, 0, 0);
        case BPF_PROG_TYPE_RAW_TRACEPOINT:
        case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
                if (strncpy_from_user(buf, user_tp_name, sizeof(buf) - 1) < 0)
@@ -4524,7 +4526,8 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
        case BPF_PROG_TYPE_EXT:
                ret = bpf_tracing_prog_attach(prog,
                                              attr->link_create.target_fd,
-                                             attr->link_create.target_btf_id);
+                                             attr->link_create.target_btf_id,
+                                             attr->link_create.tracing.cookie);
                break;
        case BPF_PROG_TYPE_LSM:
        case BPF_PROG_TYPE_TRACING:
@@ -4539,7 +4542,8 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
                else
                        ret = bpf_tracing_prog_attach(prog,
                                                      attr->link_create.target_fd,
-                                                     attr->link_create.target_btf_id);
+                                                     attr->link_create.target_btf_id,
+                                                     attr->link_create.tracing.cookie);
                break;
        case BPF_PROG_TYPE_FLOW_DISSECTOR:
        case BPF_PROG_TYPE_SK_LOOKUP:
index baf1b65d523eea346bfeb4672f5eb2a1d9ca59ba..0e9b3aefc34a96715112d6c80ecdb0de53027a9e 100644 (file)
@@ -30,9 +30,12 @@ static DEFINE_MUTEX(trampoline_mutex);
 bool bpf_prog_has_trampoline(const struct bpf_prog *prog)
 {
        enum bpf_attach_type eatype = prog->expected_attach_type;
+       enum bpf_prog_type ptype = prog->type;
 
-       return eatype == BPF_TRACE_FENTRY || eatype == BPF_TRACE_FEXIT ||
-              eatype == BPF_MODIFY_RETURN;
+       return (ptype == BPF_PROG_TYPE_TRACING &&
+               (eatype == BPF_TRACE_FENTRY || eatype == BPF_TRACE_FEXIT ||
+                eatype == BPF_MODIFY_RETURN)) ||
+               (ptype == BPF_PROG_TYPE_LSM && eatype == BPF_LSM_MAC);
 }
 
 void *bpf_jit_alloc_exec_page(void)
index 7fd11c17558decdf75688567079b33b152bcf04f..2eaac094caf8c76884c9040147424c2c33e83002 100644 (file)
@@ -1091,6 +1091,21 @@ static const struct bpf_func_proto bpf_get_attach_cookie_proto_pe = {
        .arg1_type      = ARG_PTR_TO_CTX,
 };
 
+BPF_CALL_1(bpf_get_attach_cookie_tracing, void *, ctx)
+{
+       struct bpf_trace_run_ctx *run_ctx;
+
+       run_ctx = container_of(current->bpf_ctx, struct bpf_trace_run_ctx, run_ctx);
+       return run_ctx->bpf_cookie;
+}
+
+static const struct bpf_func_proto bpf_get_attach_cookie_proto_tracing = {
+       .func           = bpf_get_attach_cookie_tracing,
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+};
+
 BPF_CALL_3(bpf_get_branch_snapshot, void *, buf, u32, size, u64, flags)
 {
 #ifndef CONFIG_X86
@@ -1719,6 +1734,8 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return bpf_prog_has_trampoline(prog) ? &bpf_get_func_ret_proto : NULL;
        case BPF_FUNC_get_func_arg_cnt:
                return bpf_prog_has_trampoline(prog) ? &bpf_get_func_arg_cnt_proto : NULL;
+       case BPF_FUNC_get_attach_cookie:
+               return bpf_prog_has_trampoline(prog) ? &bpf_get_attach_cookie_proto_tracing : NULL;
        default:
                fn = raw_tp_prog_func_proto(func_id, prog);
                if (!fn && prog->expected_attach_type == BPF_TRACE_ITER)
index 3d032ea1b6a32723609ad78c99c1d14bf741c142..bc7f89948f5497009615696e49010c46698e62a4 100644 (file)
@@ -1490,6 +1490,15 @@ union bpf_attr {
                                __aligned_u64   addrs;
                                __aligned_u64   cookies;
                        } kprobe_multi;
+                       struct {
+                               /* this is overlaid with the target_btf_id above. */
+                               __u32           target_btf_id;
+                               /* black box user-provided value passed through
+                                * to BPF program at the execution time and
+                                * accessible through bpf_get_attach_cookie() BPF helper
+                                */
+                               __u64           cookie;
+                       } tracing;
                };
        } link_create;