bpf: Add attach_type checks under bpf_prog_attach_check_attach_type
authorJiri Olsa <jolsa@kernel.org>
Wed, 9 Aug 2023 08:34:14 +0000 (10:34 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 21 Aug 2023 22:51:25 +0000 (15:51 -0700)
Add extra attach_type checks from link_create under
bpf_prog_attach_check_attach_type.

Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Yafang Shao <laoar.shao@gmail.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20230809083440.3209381-3-jolsa@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/syscall.c

index cb65854..b14036c 100644 (file)
@@ -3655,34 +3655,6 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
        return fd;
 }
 
-static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
-                                            enum bpf_attach_type attach_type)
-{
-       switch (prog->type) {
-       case BPF_PROG_TYPE_CGROUP_SOCK:
-       case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
-       case BPF_PROG_TYPE_CGROUP_SOCKOPT:
-       case BPF_PROG_TYPE_SK_LOOKUP:
-               return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
-       case BPF_PROG_TYPE_CGROUP_SKB:
-               if (!capable(CAP_NET_ADMIN))
-                       /* cg-skb progs can be loaded by unpriv user.
-                        * check permissions at attach time.
-                        */
-                       return -EPERM;
-               return prog->enforce_expected_attach_type &&
-                       prog->expected_attach_type != attach_type ?
-                       -EINVAL : 0;
-       case BPF_PROG_TYPE_KPROBE:
-               if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
-                   attach_type != BPF_TRACE_KPROBE_MULTI)
-                       return -EINVAL;
-               return 0;
-       default:
-               return 0;
-       }
-}
-
 static enum bpf_prog_type
 attach_type_to_prog_type(enum bpf_attach_type attach_type)
 {
@@ -3749,6 +3721,58 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
        }
 }
 
+static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
+                                            enum bpf_attach_type attach_type)
+{
+       enum bpf_prog_type ptype;
+
+       switch (prog->type) {
+       case BPF_PROG_TYPE_CGROUP_SOCK:
+       case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
+       case BPF_PROG_TYPE_CGROUP_SOCKOPT:
+       case BPF_PROG_TYPE_SK_LOOKUP:
+               return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
+       case BPF_PROG_TYPE_CGROUP_SKB:
+               if (!capable(CAP_NET_ADMIN))
+                       /* cg-skb progs can be loaded by unpriv user.
+                        * check permissions at attach time.
+                        */
+                       return -EPERM;
+               return prog->enforce_expected_attach_type &&
+                       prog->expected_attach_type != attach_type ?
+                       -EINVAL : 0;
+       case BPF_PROG_TYPE_EXT:
+               return 0;
+       case BPF_PROG_TYPE_NETFILTER:
+               if (attach_type != BPF_NETFILTER)
+                       return -EINVAL;
+               return 0;
+       case BPF_PROG_TYPE_PERF_EVENT:
+       case BPF_PROG_TYPE_TRACEPOINT:
+               if (attach_type != BPF_PERF_EVENT)
+                       return -EINVAL;
+               return 0;
+       case BPF_PROG_TYPE_KPROBE:
+               if (prog->expected_attach_type == BPF_TRACE_KPROBE_MULTI &&
+                   attach_type != BPF_TRACE_KPROBE_MULTI)
+                       return -EINVAL;
+               if (attach_type != BPF_PERF_EVENT &&
+                   attach_type != BPF_TRACE_KPROBE_MULTI)
+                       return -EINVAL;
+               return 0;
+       case BPF_PROG_TYPE_SCHED_CLS:
+               if (attach_type != BPF_TCX_INGRESS &&
+                   attach_type != BPF_TCX_EGRESS)
+                       return -EINVAL;
+               return 0;
+       default:
+               ptype = attach_type_to_prog_type(attach_type);
+               if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type)
+                       return -EINVAL;
+               return 0;
+       }
+}
+
 #define BPF_PROG_ATTACH_LAST_FIELD expected_revision
 
 #define BPF_F_ATTACH_MASK_BASE \
@@ -4855,7 +4879,6 @@ err_put:
 #define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
 static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 {
-       enum bpf_prog_type ptype;
        struct bpf_prog *prog;
        int ret;
 
@@ -4875,45 +4898,6 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
                goto out;
 
        switch (prog->type) {
-       case BPF_PROG_TYPE_EXT:
-               break;
-       case BPF_PROG_TYPE_NETFILTER:
-               if (attr->link_create.attach_type != BPF_NETFILTER) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               break;
-       case BPF_PROG_TYPE_PERF_EVENT:
-       case BPF_PROG_TYPE_TRACEPOINT:
-               if (attr->link_create.attach_type != BPF_PERF_EVENT) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               break;
-       case BPF_PROG_TYPE_KPROBE:
-               if (attr->link_create.attach_type != BPF_PERF_EVENT &&
-                   attr->link_create.attach_type != BPF_TRACE_KPROBE_MULTI) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               break;
-       case BPF_PROG_TYPE_SCHED_CLS:
-               if (attr->link_create.attach_type != BPF_TCX_INGRESS &&
-                   attr->link_create.attach_type != BPF_TCX_EGRESS) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               break;
-       default:
-               ptype = attach_type_to_prog_type(attr->link_create.attach_type);
-               if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-               break;
-       }
-
-       switch (prog->type) {
        case BPF_PROG_TYPE_CGROUP_SKB:
        case BPF_PROG_TYPE_CGROUP_SOCK:
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: