bpf: Replace prog_raw_tp+btf_id with prog_tracing
authorAlexei Starovoitov <ast@kernel.org>
Wed, 30 Oct 2019 22:32:11 +0000 (15:32 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 31 Oct 2019 14:16:59 +0000 (15:16 +0100)
The bpf program type raw_tp together with 'expected_attach_type'
was the most appropriate api to indicate BTF-enabled raw_tp programs.
But during development it became apparent that 'expected_attach_type'
cannot be used and new 'attach_btf_id' field had to be introduced.
Which means that the information is duplicated in two fields where
one of them is ignored.
Clean it up by introducing new program type where both
'expected_attach_type' and 'attach_btf_id' fields have
specific meaning.
In the future 'expected_attach_type' will be extended
with other attach points that have similar semantics to raw_tp.
This patch is replacing BTF-enabled BPF_PROG_TYPE_RAW_TRACEPOINT with
prog_type = BPF_RPOG_TYPE_TRACING
expected_attach_type = BPF_TRACE_RAW_TP
attach_btf_id = btf_id of raw tracepoint inside the kernel
Future patches will add
expected_attach_type = BPF_TRACE_FENTRY or BPF_TRACE_FEXIT
where programs have the same input context and the same helpers,
but different attach points.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20191030223212.953010-2-ast@kernel.org
include/linux/bpf.h
include/linux/bpf_types.h
include/uapi/linux/bpf.h
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/trace/bpf_trace.c

index 171be30fe0ae35e4f512e40b59c2789cd85f3b84..80158cff44bd17a8619de9d2dece522122e6900d 100644 (file)
@@ -373,6 +373,11 @@ enum bpf_cgroup_storage_type {
 
 #define MAX_BPF_CGROUP_STORAGE_TYPE __BPF_CGROUP_STORAGE_MAX
 
+/* The longest tracepoint has 12 args.
+ * See include/trace/bpf_probe.h
+ */
+#define MAX_BPF_FUNC_ARGS 12
+
 struct bpf_prog_stats {
        u64 cnt;
        u64 nsecs;
index 36a9c2325176b91c3f948bb917ed13ce07000d39..de14872b01ba0cdfbe7bf8c2dc92f39a5d90021f 100644 (file)
@@ -26,6 +26,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint)
 BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event)
 BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT, raw_tracepoint)
 BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, raw_tracepoint_writable)
+BPF_PROG_TYPE(BPF_PROG_TYPE_TRACING, tracing)
 #endif
 #ifdef CONFIG_CGROUP_BPF
 BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev)
index 4af8b0819a32d2f72c7218dd91503e59e05bb46d..a6bf19dabaab65f8ff5fa4297a682d7093e7f6c2 100644 (file)
@@ -173,6 +173,7 @@ enum bpf_prog_type {
        BPF_PROG_TYPE_CGROUP_SYSCTL,
        BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
        BPF_PROG_TYPE_CGROUP_SOCKOPT,
+       BPF_PROG_TYPE_TRACING,
 };
 
 enum bpf_attach_type {
@@ -199,6 +200,7 @@ enum bpf_attach_type {
        BPF_CGROUP_UDP6_RECVMSG,
        BPF_CGROUP_GETSOCKOPT,
        BPF_CGROUP_SETSOCKOPT,
+       BPF_TRACE_RAW_TP,
        __MAX_BPF_ATTACH_TYPE
 };
 
index ff522575955341a44f086a0692b15af53edf420a..985d01ced1964e68be85595f63e7743be6adf625 100644 (file)
@@ -1571,7 +1571,7 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
                           u32 btf_id)
 {
        switch (prog_type) {
-       case BPF_PROG_TYPE_RAW_TRACEPOINT:
+       case BPF_PROG_TYPE_TRACING:
                if (btf_id > BTF_MAX_TYPE)
                        return -EINVAL;
                break;
@@ -1833,13 +1833,13 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
                return PTR_ERR(prog);
 
        if (prog->type != BPF_PROG_TYPE_RAW_TRACEPOINT &&
+           prog->type != BPF_PROG_TYPE_TRACING &&
            prog->type != BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE) {
                err = -EINVAL;
                goto out_put_prog;
        }
 
-       if (prog->type == BPF_PROG_TYPE_RAW_TRACEPOINT &&
-           prog->aux->attach_btf_id) {
+       if (prog->type == BPF_PROG_TYPE_TRACING) {
                if (attr->raw_tracepoint.name) {
                        /* raw_tp name should not be specified in raw_tp
                         * programs that were verified via in-kernel BTF info
index 6b0de04f8b91860827eb88a08147ed0040218ae5..2f2374967b368db1450275c23ebbdaa45e8aeaf3 100644 (file)
@@ -9381,24 +9381,36 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
 {
        struct bpf_prog *prog = env->prog;
        u32 btf_id = prog->aux->attach_btf_id;
+       const char prefix[] = "btf_trace_";
        const struct btf_type *t;
        const char *tname;
 
-       if (prog->type == BPF_PROG_TYPE_RAW_TRACEPOINT && btf_id) {
-               const char prefix[] = "btf_trace_";
+       if (prog->type != BPF_PROG_TYPE_TRACING)
+               return 0;
 
-               t = btf_type_by_id(btf_vmlinux, btf_id);
-               if (!t) {
-                       verbose(env, "attach_btf_id %u is invalid\n", btf_id);
-                       return -EINVAL;
-               }
+       if (!btf_id) {
+               verbose(env, "Tracing programs must provide btf_id\n");
+               return -EINVAL;
+       }
+       t = btf_type_by_id(btf_vmlinux, btf_id);
+       if (!t) {
+               verbose(env, "attach_btf_id %u is invalid\n", btf_id);
+               return -EINVAL;
+       }
+       tname = btf_name_by_offset(btf_vmlinux, t->name_off);
+       if (!tname) {
+               verbose(env, "attach_btf_id %u doesn't have a name\n", btf_id);
+               return -EINVAL;
+       }
+
+       switch (prog->expected_attach_type) {
+       case BPF_TRACE_RAW_TP:
                if (!btf_type_is_typedef(t)) {
                        verbose(env, "attach_btf_id %u is not a typedef\n",
                                btf_id);
                        return -EINVAL;
                }
-               tname = btf_name_by_offset(btf_vmlinux, t->name_off);
-               if (!tname || strncmp(prefix, tname, sizeof(prefix) - 1)) {
+               if (strncmp(prefix, tname, sizeof(prefix) - 1)) {
                        verbose(env, "attach_btf_id %u points to wrong type name %s\n",
                                btf_id, tname);
                        return -EINVAL;
@@ -9419,8 +9431,10 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
                prog->aux->attach_func_name = tname;
                prog->aux->attach_func_proto = t;
                prog->aux->attach_btf_trace = true;
+               return 0;
+       default:
+               return -EINVAL;
        }
-       return 0;
 }
 
 int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
index 571c25d60710029aeb082afdbe943bca56d7637f..f50bf19f7a05d3389f964b764805c8e445f1e12b 100644 (file)
@@ -1055,10 +1055,6 @@ raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        switch (func_id) {
        case BPF_FUNC_perf_event_output:
                return &bpf_perf_event_output_proto_raw_tp;
-#ifdef CONFIG_NET
-       case BPF_FUNC_skb_output:
-               return &bpf_skb_output_proto;
-#endif
        case BPF_FUNC_get_stackid:
                return &bpf_get_stackid_proto_raw_tp;
        case BPF_FUNC_get_stack:
@@ -1068,20 +1064,44 @@ raw_tp_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        }
 }
 
+static const struct bpf_func_proto *
+tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
+{
+       switch (func_id) {
+#ifdef CONFIG_NET
+       case BPF_FUNC_skb_output:
+               return &bpf_skb_output_proto;
+#endif
+       default:
+               return raw_tp_prog_func_proto(func_id, prog);
+       }
+}
+
 static bool raw_tp_prog_is_valid_access(int off, int size,
                                        enum bpf_access_type type,
                                        const struct bpf_prog *prog,
                                        struct bpf_insn_access_aux *info)
 {
-       /* largest tracepoint in the kernel has 12 args */
-       if (off < 0 || off >= sizeof(__u64) * 12)
+       if (off < 0 || off >= sizeof(__u64) * MAX_BPF_FUNC_ARGS)
+               return false;
+       if (type != BPF_READ)
+               return false;
+       if (off % size != 0)
+               return false;
+       return true;
+}
+
+static bool tracing_prog_is_valid_access(int off, int size,
+                                        enum bpf_access_type type,
+                                        const struct bpf_prog *prog,
+                                        struct bpf_insn_access_aux *info)
+{
+       if (off < 0 || off >= sizeof(__u64) * MAX_BPF_FUNC_ARGS)
                return false;
        if (type != BPF_READ)
                return false;
        if (off % size != 0)
                return false;
-       if (!prog->aux->attach_btf_id)
-               return true;
        return btf_ctx_access(off, size, type, prog, info);
 }
 
@@ -1093,6 +1113,14 @@ const struct bpf_verifier_ops raw_tracepoint_verifier_ops = {
 const struct bpf_prog_ops raw_tracepoint_prog_ops = {
 };
 
+const struct bpf_verifier_ops tracing_verifier_ops = {
+       .get_func_proto  = tracing_prog_func_proto,
+       .is_valid_access = tracing_prog_is_valid_access,
+};
+
+const struct bpf_prog_ops tracing_prog_ops = {
+};
+
 static bool raw_tp_writable_prog_is_valid_access(int off, int size,
                                                 enum bpf_access_type type,
                                                 const struct bpf_prog *prog,