History

bpf: Centralize permissions checks for all BPF map types

This allows to do more centralized decisions later on, and generally makes it very explicit which maps are privileged and which are not (e.g., LRU_HASH and LRU_PERCPU_HASH, which are privileged HASH variants, as opposed to unprivileged HASH and HASH_PERCPU; now this is explicit and easy to verify).

Andrii Nakryiko committed 3 years ago

Commit 6c3eba11 parent 22db41214 files · +52 −44Browse files

Unified · Split

14 files
  1. kernel/bpf/bloom_filter.c +0 −3
  2. kernel/bpf/bpf_local_storage.c +0 −3
  3. kernel/bpf/bpf_struct_ops.c +0 −3
  4. kernel/bpf/cpumap.c +0 −4
  5. kernel/bpf/devmap.c +0 −3
  6. kernel/bpf/hashtab.c +0 −6
  7. kernel/bpf/lpm_trie.c +0 −3
  8. kernel/bpf/queue_stack_maps.c +0 −4
  9. kernel/bpf/reuseport_array.c +0 −3
  10. kernel/bpf/stackmap.c +0 −3
  11. kernel/bpf/syscall.c +47 −0
  12. net/core/sock_map.c +0 −4
  13. net/xdp/xskmap.c +0 −4
  14. tools/testing/selftests/bpf/prog_tests/unpriv_bpf_disabled.c +5 −1
kernel/bpf/bloom_filter.c+0−3
@@ -86,9 +86,6 @@ static struct bpf_map *bloom_map_alloc(union bpf_attr *attr) · 85 unmodified lines
86 int numa_node = bpf_map_attr_numa_node(attr);86 int numa_node = bpf_map_attr_numa_node(attr);
87 struct bpf_bloom_filter *bloom;87 struct bpf_bloom_filter *bloom;
88 88
89 if (!bpf_capable())
90 return ERR_PTR(-EPERM);
91
92 if (attr->key_size != 0 || attr->value_size == 0 ||89 if (attr->key_size != 0 || attr->value_size == 0 ||
93 attr->max_entries == 0 ||90 attr->max_entries == 0 ||
94 attr->map_flags & ~BLOOM_CREATE_FLAG_MASK ||91 attr->map_flags & ~BLOOM_CREATE_FLAG_MASK ||
kernel/bpf/bpf_local_storage.c+0−3
@@ -723,9 +723,6 @@ int bpf_local_storage_map_alloc_check(union bpf_attr *attr) · 722 unmodified lines
723 !attr->btf_key_type_id || !attr->btf_value_type_id)723 !attr->btf_key_type_id || !attr->btf_value_type_id)
724 return -EINVAL;724 return -EINVAL;
725 725
726 if (!bpf_capable())
727 return -EPERM;
728
729 if (attr->value_size > BPF_LOCAL_STORAGE_MAX_VALUE_SIZE)726 if (attr->value_size > BPF_LOCAL_STORAGE_MAX_VALUE_SIZE)
730 return -E2BIG;727 return -E2BIG;
731 728
kernel/bpf/bpf_struct_ops.c+0−3
@@ -655,9 +655,6 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) · 654 unmodified lines
655 const struct btf_type *t, *vt;655 const struct btf_type *t, *vt;
656 struct bpf_map *map;656 struct bpf_map *map;
657 657
658 if (!bpf_capable())
659 return ERR_PTR(-EPERM);
660
661 st_ops = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id);658 st_ops = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id);
662 if (!st_ops)659 if (!st_ops)
663 return ERR_PTR(-ENOTSUPP);660 return ERR_PTR(-ENOTSUPP);
kernel/bpf/cpumap.c+0−4
@@ -28,7 +28,6 @@ · 27 unmodified lines
28#include <linux/sched.h>28#include <linux/sched.h>
29#include <linux/workqueue.h>29#include <linux/workqueue.h>
30#include <linux/kthread.h>30#include <linux/kthread.h>
31#include <linux/capability.h>
32#include <trace/events/xdp.h>31#include <trace/events/xdp.h>
33#include <linux/btf_ids.h>32#include <linux/btf_ids.h>
34 33
@@ -89,9 +88,6 @@ static struct bpf_map *cpu_map_alloc(union bpf_attr *attr) · 54 unmodified lines
89 u32 value_size = attr->value_size;88 u32 value_size = attr->value_size;
90 struct bpf_cpu_map *cmap;89 struct bpf_cpu_map *cmap;
91 90
92 if (!bpf_capable())
93 return ERR_PTR(-EPERM);
94
95 /* check sanity of attributes */91 /* check sanity of attributes */
96 if (attr->max_entries == 0 || attr->key_size != 4 ||92 if (attr->max_entries == 0 || attr->key_size != 4 ||
97 (value_size != offsetofend(struct bpf_cpumap_val, qsize) &&93 (value_size != offsetofend(struct bpf_cpumap_val, qsize) &&
kernel/bpf/devmap.c+0−3
@@ -160,9 +160,6 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) · 159 unmodified lines
160 struct bpf_dtab *dtab;160 struct bpf_dtab *dtab;
161 int err;161 int err;
162 162
163 if (!capable(CAP_NET_ADMIN))
164 return ERR_PTR(-EPERM);
165
166 dtab = bpf_map_area_alloc(sizeof(*dtab), NUMA_NO_NODE);163 dtab = bpf_map_area_alloc(sizeof(*dtab), NUMA_NO_NODE);
167 if (!dtab)164 if (!dtab)
168 return ERR_PTR(-ENOMEM);165 return ERR_PTR(-ENOMEM);
kernel/bpf/hashtab.c+0−6
@@ -422,12 +422,6 @@ static int htab_map_alloc_check(union bpf_attr *attr) · 421 unmodified lines
422 BUILD_BUG_ON(offsetof(struct htab_elem, fnode.next) !=422 BUILD_BUG_ON(offsetof(struct htab_elem, fnode.next) !=
423 offsetof(struct htab_elem, hash_node.pprev));423 offsetof(struct htab_elem, hash_node.pprev));
424 424
425 if (lru && !bpf_capable())
426 /* LRU implementation is much complicated than other
427 * maps. Hence, limit to CAP_BPF.
428 */
429 return -EPERM;
430
431 if (zero_seed && !capable(CAP_SYS_ADMIN))425 if (zero_seed && !capable(CAP_SYS_ADMIN))
432 /* Guard against local DoS, and discourage production use. */426 /* Guard against local DoS, and discourage production use. */
433 return -EPERM;427 return -EPERM;
kernel/bpf/lpm_trie.c+0−3
@@ -544,9 +544,6 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr) · 543 unmodified lines
544{544{
545 struct lpm_trie *trie;545 struct lpm_trie *trie;
546 546
547 if (!bpf_capable())
548 return ERR_PTR(-EPERM);
549
550 /* check sanity of attributes */547 /* check sanity of attributes */
551 if (attr->max_entries == 0 ||548 if (attr->max_entries == 0 ||
552 !(attr->map_flags & BPF_F_NO_PREALLOC) ||549 !(attr->map_flags & BPF_F_NO_PREALLOC) ||
kernel/bpf/queue_stack_maps.c+0−4
@@ -7,7 +7,6 @@ · 6 unmodified lines
7#include <linux/bpf.h>7#include <linux/bpf.h>
8#include <linux/list.h>8#include <linux/list.h>
9#include <linux/slab.h>9#include <linux/slab.h>
10#include <linux/capability.h>
11#include <linux/btf_ids.h>10#include <linux/btf_ids.h>
12#include "percpu_freelist.h"11#include "percpu_freelist.h"
13 12
@@ -46,9 +45,6 @@ static bool queue_stack_map_is_full(struct bpf_queue_stack *qs) · 32 unmodified lines
46/* Called from syscall */45/* Called from syscall */
47static int queue_stack_map_alloc_check(union bpf_attr *attr)46static int queue_stack_map_alloc_check(union bpf_attr *attr)
48{47{
49 if (!bpf_capable())
50 return -EPERM;
51
52 /* check sanity of attributes */48 /* check sanity of attributes */
53 if (attr->max_entries == 0 || attr->key_size != 0 ||49 if (attr->max_entries == 0 || attr->key_size != 0 ||
54 attr->value_size == 0 ||50 attr->value_size == 0 ||
kernel/bpf/reuseport_array.c+0−3
@@ -151,9 +151,6 @@ static struct bpf_map *reuseport_array_alloc(union bpf_attr *attr) · 150 unmodified lines
151 int numa_node = bpf_map_attr_numa_node(attr);151 int numa_node = bpf_map_attr_numa_node(attr);
152 struct reuseport_array *array;152 struct reuseport_array *array;
153 153
154 if (!bpf_capable())
155 return ERR_PTR(-EPERM);
156
157 /* allocate all map elements and zero-initialize them */154 /* allocate all map elements and zero-initialize them */
158 array = bpf_map_area_alloc(struct_size(array, ptrs, attr->max_entries), numa_node);155 array = bpf_map_area_alloc(struct_size(array, ptrs, attr->max_entries), numa_node);
159 if (!array)156 if (!array)
kernel/bpf/stackmap.c+0−3
@@ -74,9 +74,6 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) · 73 unmodified lines
74 u64 cost, n_buckets;74 u64 cost, n_buckets;
75 int err;75 int err;
76 76
77 if (!bpf_capable())
78 return ERR_PTR(-EPERM);
79
80 if (attr->map_flags & ~STACK_CREATE_FLAG_MASK)77 if (attr->map_flags & ~STACK_CREATE_FLAG_MASK)
81 return ERR_PTR(-EINVAL);78 return ERR_PTR(-EINVAL);
82 79
kernel/bpf/syscall.c+47−0
@@ -1156,6 +1156,53 @@ static int map_create(union bpf_attr *attr) · 1155 unmodified lines
1156 if (sysctl_unprivileged_bpf_disabled && !bpf_capable())1156 if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
1157 return -EPERM;1157 return -EPERM;
1158 1158
1159 /* check privileged map type permissions */
1160 switch (map_type) {
1161 case BPF_MAP_TYPE_ARRAY:
1162 case BPF_MAP_TYPE_PERCPU_ARRAY:
1163 case BPF_MAP_TYPE_PROG_ARRAY:
1164 case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
1165 case BPF_MAP_TYPE_CGROUP_ARRAY:
1166 case BPF_MAP_TYPE_ARRAY_OF_MAPS:
1167 case BPF_MAP_TYPE_HASH:
1168 case BPF_MAP_TYPE_PERCPU_HASH:
1169 case BPF_MAP_TYPE_HASH_OF_MAPS:
1170 case BPF_MAP_TYPE_RINGBUF:
1171 case BPF_MAP_TYPE_USER_RINGBUF:
1172 case BPF_MAP_TYPE_CGROUP_STORAGE:
1173 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
1174 /* unprivileged */
1175 break;
1176 case BPF_MAP_TYPE_SK_STORAGE:
1177 case BPF_MAP_TYPE_INODE_STORAGE:
1178 case BPF_MAP_TYPE_TASK_STORAGE:
1179 case BPF_MAP_TYPE_CGRP_STORAGE:
1180 case BPF_MAP_TYPE_BLOOM_FILTER:
1181 case BPF_MAP_TYPE_LPM_TRIE:
1182 case BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
1183 case BPF_MAP_TYPE_STACK_TRACE:
1184 case BPF_MAP_TYPE_QUEUE:
1185 case BPF_MAP_TYPE_STACK:
1186 case BPF_MAP_TYPE_LRU_HASH:
1187 case BPF_MAP_TYPE_LRU_PERCPU_HASH:
1188 case BPF_MAP_TYPE_STRUCT_OPS:
1189 case BPF_MAP_TYPE_CPUMAP:
1190 if (!bpf_capable())
1191 return -EPERM;
1192 break;
1193 case BPF_MAP_TYPE_SOCKMAP:
1194 case BPF_MAP_TYPE_SOCKHASH:
1195 case BPF_MAP_TYPE_DEVMAP:
1196 case BPF_MAP_TYPE_DEVMAP_HASH:
1197 case BPF_MAP_TYPE_XSKMAP:
1198 if (!capable(CAP_NET_ADMIN))
1199 return -EPERM;
1200 break;
1201 default:
1202 WARN(1, "unsupported map type %d", map_type);
1203 return -EPERM;
1204 }
1205
1159 map = ops->map_alloc(attr);1206 map = ops->map_alloc(attr);
1160 if (IS_ERR(map))1207 if (IS_ERR(map))
1161 return PTR_ERR(map);1208 return PTR_ERR(map);
net/core/sock_map.c+0−4
@@ -32,8 +32,6 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr) · 31 unmodified lines
32{32{
33 struct bpf_stab *stab;33 struct bpf_stab *stab;
34 34
35 if (!capable(CAP_NET_ADMIN))
36 return ERR_PTR(-EPERM);
37 if (attr->max_entries == 0 ||35 if (attr->max_entries == 0 ||
38 attr->key_size != 4 ||36 attr->key_size != 4 ||
39 (attr->value_size != sizeof(u32) &&37 (attr->value_size != sizeof(u32) &&
@@ -1085,8 +1083,6 @@ static struct bpf_map *sock_hash_alloc(union bpf_attr *attr) · 1045 unmodified lines
1085 struct bpf_shtab *htab;1083 struct bpf_shtab *htab;
1086 int i, err;1084 int i, err;
1087 1085
1088 if (!capable(CAP_NET_ADMIN))
1089 return ERR_PTR(-EPERM);
1090 if (attr->max_entries == 0 ||1086 if (attr->max_entries == 0 ||
1091 attr->key_size == 0 ||1087 attr->key_size == 0 ||
1092 (attr->value_size != sizeof(u32) &&1088 (attr->value_size != sizeof(u32) &&
net/xdp/xskmap.c+0−4
@@ -5,7 +5,6 @@ · 4 unmodified lines
5 5
6#include <linux/bpf.h>6#include <linux/bpf.h>
7#include <linux/filter.h>7#include <linux/filter.h>
8#include <linux/capability.h>
9#include <net/xdp_sock.h>8#include <net/xdp_sock.h>
10#include <linux/slab.h>9#include <linux/slab.h>
11#include <linux/sched.h>10#include <linux/sched.h>
@@ -68,9 +67,6 @@ static struct bpf_map *xsk_map_alloc(union bpf_attr *attr) · 56 unmodified lines
68 int numa_node;67 int numa_node;
69 u64 size;68 u64 size;
70 69
71 if (!capable(CAP_NET_ADMIN))
72 return ERR_PTR(-EPERM);
73
74 if (attr->max_entries == 0 || attr->key_size != 4 ||70 if (attr->max_entries == 0 || attr->key_size != 4 ||
75 attr->value_size != 4 ||71 attr->value_size != 4 ||
76 attr->map_flags & ~(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY))72 attr->map_flags & ~(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY))
tools/testing/selftests/bpf/prog_tests/unpriv_bpf_disabled.c+5−1
@@ -171,7 +171,11 @@ static void test_unpriv_bpf_disabled_negative(struct test_unpriv_bpf_disabled *s · 170 unmodified lines
171 prog_insns, prog_insn_cnt, &load_opts),171 prog_insns, prog_insn_cnt, &load_opts),
172 -EPERM, "prog_load_fails");172 -EPERM, "prog_load_fails");
173 173
174 for (i = BPF_MAP_TYPE_HASH; i <= BPF_MAP_TYPE_BLOOM_FILTER; i++)174 /* some map types require particular correct parameters which could be
175 * sanity-checked before enforcing -EPERM, so only validate that
176 * the simple ARRAY and HASH maps are failing with -EPERM
177 */
178 for (i = BPF_MAP_TYPE_HASH; i <= BPF_MAP_TYPE_ARRAY; i++)
175 ASSERT_EQ(bpf_map_create(i, NULL, sizeof(int), sizeof(int), 1, NULL),179 ASSERT_EQ(bpf_map_create(i, NULL, sizeof(int), sizeof(int), 1, NULL),
176 -EPERM, "map_create_fails");180 -EPERM, "map_create_fails");
177 181