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 | 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 || |
| @@ -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 | ||
| @@ -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); |
| @@ -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) && |
| @@ -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); |
| @@ -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; |
| @@ -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) || |
| @@ -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 */ |
| 47 | static int queue_stack_map_alloc_check(union bpf_attr *attr) | 46 | static 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 || |
| @@ -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) |
| @@ -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 | ||
| @@ -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); |
| @@ -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) && |
| @@ -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)) |
| @@ -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 | ||