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).
Unified · Split
| @@ -86,9 +86,6 @@ static struct bpf_map *bloom_map_alloc(union bpf_attr *attr) · 85 unmodified lines | ||
| 86 | 86 | int numa_node = bpf_map_attr_numa_node(attr); |
| 87 | 87 | struct bpf_bloom_filter *bloom; |
| 88 | 88 | |
| 89 | − if (!bpf_capable()) | |
| 90 | − return ERR_PTR(-EPERM); | |
| 91 | − | |
| 92 | 89 | if (attr->key_size != 0 || attr->value_size == 0 || |
| 93 | 90 | attr->max_entries == 0 || |
| 94 | 91 | attr->map_flags & ~BLOOM_CREATE_FLAG_MASK || |
| @@ -723,9 +723,6 @@ int bpf_local_storage_map_alloc_check(union bpf_attr *attr) · 722 unmodified lines | ||
| 723 | 723 | !attr->btf_key_type_id || !attr->btf_value_type_id) |
| 724 | 724 | return -EINVAL; |
| 725 | 725 | |
| 726 | − if (!bpf_capable()) | |
| 727 | − return -EPERM; | |
| 728 | − | |
| 729 | 726 | if (attr->value_size > BPF_LOCAL_STORAGE_MAX_VALUE_SIZE) |
| 730 | 727 | return -E2BIG; |
| 731 | 728 | |
| @@ -655,9 +655,6 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr) · 654 unmodified lines | ||
| 655 | 655 | const struct btf_type *t, *vt; |
| 656 | 656 | struct bpf_map *map; |
| 657 | 657 | |
| 658 | − if (!bpf_capable()) | |
| 659 | − return ERR_PTR(-EPERM); | |
| 660 | − | |
| 661 | 658 | st_ops = bpf_struct_ops_find_value(attr->btf_vmlinux_value_type_id); |
| 662 | 659 | if (!st_ops) |
| 663 | 660 | return ERR_PTR(-ENOTSUPP); |
| @@ -28,7 +28,6 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/sched.h> |
| 29 | 29 | #include <linux/workqueue.h> |
| 30 | 30 | #include <linux/kthread.h> |
| 31 | −#include <linux/capability.h> | |
| 32 | 31 | #include <trace/events/xdp.h> |
| 33 | 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 | 88 | u32 value_size = attr->value_size; |
| 90 | 89 | struct bpf_cpu_map *cmap; |
| 91 | 90 | |
| 92 | − if (!bpf_capable()) | |
| 93 | − return ERR_PTR(-EPERM); | |
| 94 | − | |
| 95 | 91 | /* check sanity of attributes */ |
| 96 | 92 | if (attr->max_entries == 0 || attr->key_size != 4 || |
| 97 | 93 | (value_size != offsetofend(struct bpf_cpumap_val, qsize) && |
| @@ -160,9 +160,6 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr) · 159 unmodified lines | ||
| 160 | 160 | struct bpf_dtab *dtab; |
| 161 | 161 | int err; |
| 162 | 162 | |
| 163 | − if (!capable(CAP_NET_ADMIN)) | |
| 164 | − return ERR_PTR(-EPERM); | |
| 165 | − | |
| 166 | 163 | dtab = bpf_map_area_alloc(sizeof(*dtab), NUMA_NO_NODE); |
| 167 | 164 | if (!dtab) |
| 168 | 165 | return ERR_PTR(-ENOMEM); |
| @@ -422,12 +422,6 @@ static int htab_map_alloc_check(union bpf_attr *attr) · 421 unmodified lines | ||
| 422 | 422 | BUILD_BUG_ON(offsetof(struct htab_elem, fnode.next) != |
| 423 | 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 | 425 | if (zero_seed && !capable(CAP_SYS_ADMIN)) |
| 432 | 426 | /* Guard against local DoS, and discourage production use. */ |
| 433 | 427 | return -EPERM; |
| @@ -544,9 +544,6 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr) · 543 unmodified lines | ||
| 544 | 544 | { |
| 545 | 545 | struct lpm_trie *trie; |
| 546 | 546 | |
| 547 | − if (!bpf_capable()) | |
| 548 | − return ERR_PTR(-EPERM); | |
| 549 | − | |
| 550 | 547 | /* check sanity of attributes */ |
| 551 | 548 | if (attr->max_entries == 0 || |
| 552 | 549 | !(attr->map_flags & BPF_F_NO_PREALLOC) || |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/bpf.h> |
| 8 | 8 | #include <linux/list.h> |
| 9 | 9 | #include <linux/slab.h> |
| 10 | −#include <linux/capability.h> | |
| 11 | 10 | #include <linux/btf_ids.h> |
| 12 | 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 | 45 | /* Called from syscall */ |
| 47 | 46 | static int queue_stack_map_alloc_check(union bpf_attr *attr) |
| 48 | 47 | { |
| 49 | − if (!bpf_capable()) | |
| 50 | − return -EPERM; | |
| 51 | − | |
| 52 | 48 | /* check sanity of attributes */ |
| 53 | 49 | if (attr->max_entries == 0 || attr->key_size != 0 || |
| 54 | 50 | attr->value_size == 0 || |
| @@ -151,9 +151,6 @@ static struct bpf_map *reuseport_array_alloc(union bpf_attr *attr) · 150 unmodified lines | ||
| 151 | 151 | int numa_node = bpf_map_attr_numa_node(attr); |
| 152 | 152 | struct reuseport_array *array; |
| 153 | 153 | |
| 154 | − if (!bpf_capable()) | |
| 155 | − return ERR_PTR(-EPERM); | |
| 156 | − | |
| 157 | 154 | /* allocate all map elements and zero-initialize them */ |
| 158 | 155 | array = bpf_map_area_alloc(struct_size(array, ptrs, attr->max_entries), numa_node); |
| 159 | 156 | if (!array) |
| @@ -74,9 +74,6 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) · 73 unmodified lines | ||
| 74 | 74 | u64 cost, n_buckets; |
| 75 | 75 | int err; |
| 76 | 76 | |
| 77 | − if (!bpf_capable()) | |
| 78 | − return ERR_PTR(-EPERM); | |
| 79 | − | |
| 80 | 77 | if (attr->map_flags & ~STACK_CREATE_FLAG_MASK) |
| 81 | 78 | return ERR_PTR(-EINVAL); |
| 82 | 79 | |
| @@ -1156,6 +1156,53 @@ static int map_create(union bpf_attr *attr) · 1155 unmodified lines | ||
| 1156 | 1156 | if (sysctl_unprivileged_bpf_disabled && !bpf_capable()) |
| 1157 | 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 | 1206 | map = ops->map_alloc(attr); |
| 1160 | 1207 | if (IS_ERR(map)) |
| 1161 | 1208 | return PTR_ERR(map); |
| @@ -32,8 +32,6 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr) · 31 unmodified lines | ||
| 32 | 32 | { |
| 33 | 33 | struct bpf_stab *stab; |
| 34 | 34 | |
| 35 | − if (!capable(CAP_NET_ADMIN)) | |
| 36 | − return ERR_PTR(-EPERM); | |
| 37 | 35 | if (attr->max_entries == 0 || |
| 38 | 36 | attr->key_size != 4 || |
| 39 | 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 | 1083 | struct bpf_shtab *htab; |
| 1086 | 1084 | int i, err; |
| 1087 | 1085 | |
| 1088 | − if (!capable(CAP_NET_ADMIN)) | |
| 1089 | − return ERR_PTR(-EPERM); | |
| 1090 | 1086 | if (attr->max_entries == 0 || |
| 1091 | 1087 | attr->key_size == 0 || |
| 1092 | 1088 | (attr->value_size != sizeof(u32) && |
| @@ -5,7 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #include <linux/bpf.h> |
| 7 | 7 | #include <linux/filter.h> |
| 8 | −#include <linux/capability.h> | |
| 9 | 8 | #include <net/xdp_sock.h> |
| 10 | 9 | #include <linux/slab.h> |
| 11 | 10 | #include <linux/sched.h> |
| @@ -68,9 +67,6 @@ static struct bpf_map *xsk_map_alloc(union bpf_attr *attr) · 56 unmodified lines | ||
| 68 | 67 | int numa_node; |
| 69 | 68 | u64 size; |
| 70 | 69 | |
| 71 | − if (!capable(CAP_NET_ADMIN)) | |
| 72 | − return ERR_PTR(-EPERM); | |
| 73 | − | |
| 74 | 70 | if (attr->max_entries == 0 || attr->key_size != 4 || |
| 75 | 71 | attr->value_size != 4 || |
| 76 | 72 | attr->map_flags & ~(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)) |
| @@ -171,7 +171,11 @@ static void test_unpriv_bpf_disabled_negative(struct test_unpriv_bpf_disabled *s · 170 unmodified lines | ||
| 171 | 171 | prog_insns, prog_insn_cnt, &load_opts), |
| 172 | 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 | 179 | ASSERT_EQ(bpf_map_create(i, NULL, sizeof(int), sizeof(int), 1, NULL), |
| 176 | 180 | -EPERM, "map_create_fails"); |
| 177 | 181 | |