blob: e9a3ebc00e08fb8cf7b262268658a171c62ee9bf [file] [log] [blame]
Thomas Gleixner5b497af2019-05-29 07:18:09 -07001// SPDX-License-Identifier: GPL-2.0-only
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07002/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07003 */
4#include <linux/bpf.h>
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01005#include <linux/bpf_trace.h>
Sean Youngf4364dc2018-05-27 12:24:09 +01006#include <linux/bpf_lirc.h>
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07007#include <linux/btf.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07008#include <linux/syscalls.h>
9#include <linux/slab.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010010#include <linux/sched/signal.h>
Daniel Borkmannd407bd22017-01-18 15:14:17 +010011#include <linux/vmalloc.h>
12#include <linux/mmzone.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070013#include <linux/anon_inodes.h>
Yonghong Song41bdc4b2018-05-24 11:21:09 -070014#include <linux/fdtable.h>
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -070015#include <linux/file.h>
Yonghong Song41bdc4b2018-05-24 11:21:09 -070016#include <linux/fs.h>
Alexei Starovoitov09756af2014-09-26 00:17:00 -070017#include <linux/license.h>
18#include <linux/filter.h>
Alexei Starovoitov25415172015-03-25 12:49:20 -070019#include <linux/version.h>
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +010020#include <linux/kernel.h>
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070021#include <linux/idr.h>
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -070022#include <linux/cred.h>
23#include <linux/timekeeping.h>
24#include <linux/ctype.h>
Mark Rutland9ef09e32018-05-03 17:04:59 +010025#include <linux/nospec.h>
Daniel Borkmannbae141f2019-12-06 22:49:34 +010026#include <linux/audit.h>
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -070027#include <uapi/linux/btf.h>
Christoph Hellwig041de932020-06-01 21:52:02 -070028#include <asm/pgtable.h>
KP Singh9e4e01d2020-03-29 01:43:52 +010029#include <linux/bpf_lsm.h>
Andrii Nakryiko457f4432020-05-29 00:54:20 -070030#include <linux/poll.h>
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +020031#include <linux/bpf-netns.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070032
Daniel Borkmannda765a22019-11-22 21:07:58 +010033#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
34 (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
35 (map)->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
36#define IS_FD_PROG_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY)
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070037#define IS_FD_HASH(map) ((map)->map_type == BPF_MAP_TYPE_HASH_OF_MAPS)
Daniel Borkmannda765a22019-11-22 21:07:58 +010038#define IS_FD_MAP(map) (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map) || \
39 IS_FD_HASH(map))
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070040
Chenbo Feng6e71b042017-10-18 13:00:22 -070041#define BPF_OBJ_FLAG_MASK (BPF_F_RDONLY | BPF_F_WRONLY)
42
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080043DEFINE_PER_CPU(int, bpf_prog_active);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070044static DEFINE_IDR(prog_idr);
45static DEFINE_SPINLOCK(prog_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -070046static DEFINE_IDR(map_idr);
47static DEFINE_SPINLOCK(map_idr_lock);
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -070048static DEFINE_IDR(link_idr);
49static DEFINE_SPINLOCK(link_idr_lock);
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080050
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070051int sysctl_unprivileged_bpf_disabled __read_mostly;
52
Johannes Berg40077e02017-04-11 15:34:58 +020053static const struct bpf_map_ops * const bpf_map_types[] = {
Alexei Starovoitov91cc1a92019-11-14 10:57:15 -080054#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
Johannes Berg40077e02017-04-11 15:34:58 +020055#define BPF_MAP_TYPE(_id, _ops) \
56 [_id] = &_ops,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -070057#define BPF_LINK_TYPE(_id, _name)
Johannes Berg40077e02017-04-11 15:34:58 +020058#include <linux/bpf_types.h>
59#undef BPF_PROG_TYPE
60#undef BPF_MAP_TYPE
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -070061#undef BPF_LINK_TYPE
Johannes Berg40077e02017-04-11 15:34:58 +020062};
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070063
Mickaël Salaün752ba562017-08-07 20:45:20 +020064/*
65 * If we're handed a bigger struct than we know of, ensure all the unknown bits
66 * are 0 - i.e. new user-space does not rely on any kernel feature extensions
67 * we don't know about yet.
68 *
69 * There is a ToCToU between this function call and the following
70 * copy_from_user() call. However, this is not a concern since this function is
71 * meant to be a future-proofing of bits.
72 */
Martin KaFai Laudcab51f2018-05-22 15:03:31 -070073int bpf_check_uarg_tail_zero(void __user *uaddr,
74 size_t expected_size,
75 size_t actual_size)
Mickaël Salaün58291a72017-08-07 20:45:19 +020076{
77 unsigned char __user *addr;
78 unsigned char __user *end;
79 unsigned char val;
80 int err;
81
Mickaël Salaün752ba562017-08-07 20:45:20 +020082 if (unlikely(actual_size > PAGE_SIZE)) /* silly large */
83 return -E2BIG;
84
Linus Torvalds96d4f262019-01-03 18:57:57 -080085 if (unlikely(!access_ok(uaddr, actual_size)))
Mickaël Salaün752ba562017-08-07 20:45:20 +020086 return -EFAULT;
87
Mickaël Salaün58291a72017-08-07 20:45:19 +020088 if (actual_size <= expected_size)
89 return 0;
90
91 addr = uaddr + expected_size;
92 end = uaddr + actual_size;
93
94 for (; addr < end; addr++) {
95 err = get_user(val, addr);
96 if (err)
97 return err;
98 if (val)
99 return -E2BIG;
100 }
101
102 return 0;
103}
104
Jakub Kicinskia3884572018-01-11 20:29:09 -0800105const struct bpf_map_ops bpf_map_offload_ops = {
106 .map_alloc = bpf_map_offload_map_alloc,
107 .map_free = bpf_map_offload_map_free,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200108 .map_check_btf = map_check_no_btf,
Jakub Kicinskia3884572018-01-11 20:29:09 -0800109};
110
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700111static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
112{
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800113 const struct bpf_map_ops *ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100114 u32 type = attr->map_type;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700115 struct bpf_map *map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800116 int err;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700117
Mark Rutland9ef09e32018-05-03 17:04:59 +0100118 if (type >= ARRAY_SIZE(bpf_map_types))
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800119 return ERR_PTR(-EINVAL);
Mark Rutland9ef09e32018-05-03 17:04:59 +0100120 type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types));
121 ops = bpf_map_types[type];
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800122 if (!ops)
Johannes Berg40077e02017-04-11 15:34:58 +0200123 return ERR_PTR(-EINVAL);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700124
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800125 if (ops->map_alloc_check) {
126 err = ops->map_alloc_check(attr);
127 if (err)
128 return ERR_PTR(err);
129 }
Jakub Kicinskia3884572018-01-11 20:29:09 -0800130 if (attr->map_ifindex)
131 ops = &bpf_map_offload_ops;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800132 map = ops->map_alloc(attr);
Johannes Berg40077e02017-04-11 15:34:58 +0200133 if (IS_ERR(map))
134 return map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800135 map->ops = ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100136 map->map_type = type;
Johannes Berg40077e02017-04-11 15:34:58 +0200137 return map;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700138}
139
Brian Vazquez15c14a32020-01-15 10:43:00 -0800140static u32 bpf_map_value_size(struct bpf_map *map)
141{
142 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
143 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
144 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
145 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
146 return round_up(map->value_size, 8) * num_possible_cpus();
147 else if (IS_FD_MAP(map))
148 return sizeof(u32);
149 else
150 return map->value_size;
151}
152
153static void maybe_wait_bpf_programs(struct bpf_map *map)
154{
155 /* Wait for any running BPF programs to complete so that
156 * userspace, when we return to it, knows that all programs
157 * that could be running use the new map value.
158 */
159 if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
160 map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
161 synchronize_rcu();
162}
163
164static int bpf_map_update_value(struct bpf_map *map, struct fd f, void *key,
165 void *value, __u64 flags)
166{
167 int err;
168
169 /* Need to create a kthread, thus must support schedule */
170 if (bpf_map_is_dev_bound(map)) {
171 return bpf_map_offload_update_elem(map, key, value, flags);
172 } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
173 map->map_type == BPF_MAP_TYPE_SOCKHASH ||
174 map->map_type == BPF_MAP_TYPE_SOCKMAP ||
175 map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
176 return map->ops->map_update_elem(map, key, value, flags);
177 } else if (IS_FD_PROG_ARRAY(map)) {
178 return bpf_fd_array_map_update_elem(map, f.file, key, value,
179 flags);
180 }
181
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100182 bpf_disable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800183 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
184 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
185 err = bpf_percpu_hash_update(map, key, value, flags);
186 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
187 err = bpf_percpu_array_update(map, key, value, flags);
188 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
189 err = bpf_percpu_cgroup_storage_update(map, key, value,
190 flags);
191 } else if (IS_FD_ARRAY(map)) {
192 rcu_read_lock();
193 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
194 flags);
195 rcu_read_unlock();
196 } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
197 rcu_read_lock();
198 err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
199 flags);
200 rcu_read_unlock();
201 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
202 /* rcu_read_lock() is not needed */
203 err = bpf_fd_reuseport_array_update_elem(map, key, value,
204 flags);
205 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
206 map->map_type == BPF_MAP_TYPE_STACK) {
207 err = map->ops->map_push_elem(map, value, flags);
208 } else {
209 rcu_read_lock();
210 err = map->ops->map_update_elem(map, key, value, flags);
211 rcu_read_unlock();
212 }
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100213 bpf_enable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800214 maybe_wait_bpf_programs(map);
215
216 return err;
217}
218
219static int bpf_map_copy_value(struct bpf_map *map, void *key, void *value,
220 __u64 flags)
221{
222 void *ptr;
223 int err;
224
Brian Vazquezcb4d03a2020-01-15 10:43:01 -0800225 if (bpf_map_is_dev_bound(map))
226 return bpf_map_offload_lookup_elem(map, key, value);
Brian Vazquez15c14a32020-01-15 10:43:00 -0800227
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100228 bpf_disable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800229 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
230 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
231 err = bpf_percpu_hash_copy(map, key, value);
232 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
233 err = bpf_percpu_array_copy(map, key, value);
234 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
235 err = bpf_percpu_cgroup_storage_copy(map, key, value);
236 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
237 err = bpf_stackmap_copy(map, key, value);
238 } else if (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map)) {
239 err = bpf_fd_array_map_lookup_elem(map, key, value);
240 } else if (IS_FD_HASH(map)) {
241 err = bpf_fd_htab_map_lookup_elem(map, key, value);
242 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
243 err = bpf_fd_reuseport_array_lookup_elem(map, key, value);
244 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
245 map->map_type == BPF_MAP_TYPE_STACK) {
246 err = map->ops->map_peek_elem(map, value);
247 } else if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
248 /* struct_ops map requires directly updating "value" */
249 err = bpf_struct_ops_map_sys_lookup_elem(map, key, value);
250 } else {
251 rcu_read_lock();
252 if (map->ops->map_lookup_elem_sys_only)
253 ptr = map->ops->map_lookup_elem_sys_only(map, key);
254 else
255 ptr = map->ops->map_lookup_elem(map, key);
256 if (IS_ERR(ptr)) {
257 err = PTR_ERR(ptr);
258 } else if (!ptr) {
259 err = -ENOENT;
260 } else {
261 err = 0;
262 if (flags & BPF_F_LOCK)
263 /* lock 'ptr' and copy everything but lock */
264 copy_map_value_locked(map, value, ptr, true);
265 else
266 copy_map_value(map, value, ptr);
267 /* mask lock, since value wasn't zero inited */
268 check_and_init_map_lock(map, value);
269 }
270 rcu_read_unlock();
271 }
272
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100273 bpf_enable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800274 maybe_wait_bpf_programs(map);
275
276 return err;
277}
278
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100279static void *__bpf_map_area_alloc(u64 size, int numa_node, bool mmapable)
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100280{
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100281 /* We really just want to fail instead of triggering OOM killer
282 * under memory pressure, therefore we set __GFP_NORETRY to kmalloc,
283 * which is used for lower order allocation requests.
284 *
285 * It has been observed that higher order allocation requests done by
286 * vmalloc with __GFP_NORETRY being set might fail due to not trying
287 * to reclaim memory from the page cache, thus we set
288 * __GFP_RETRY_MAYFAIL to avoid such situations.
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100289 */
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100290
Christoph Hellwig041de932020-06-01 21:52:02 -0700291 const gfp_t gfp = __GFP_NOWARN | __GFP_ZERO;
292 unsigned int flags = 0;
293 unsigned long align = 1;
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100294 void *area;
295
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100296 if (size >= SIZE_MAX)
297 return NULL;
298
Andrii Nakryikofc970222019-11-17 09:28:04 -0800299 /* kmalloc()'ed memory can't be mmap()'ed */
Christoph Hellwig041de932020-06-01 21:52:02 -0700300 if (mmapable) {
301 BUG_ON(!PAGE_ALIGNED(size));
302 align = SHMLBA;
303 flags = VM_USERMAP;
304 } else if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
305 area = kmalloc_node(size, gfp | GFP_USER | __GFP_NORETRY,
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100306 numa_node);
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100307 if (area != NULL)
308 return area;
309 }
Christoph Hellwig041de932020-06-01 21:52:02 -0700310
311 return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
312 gfp | GFP_KERNEL | __GFP_RETRY_MAYFAIL, PAGE_KERNEL,
313 flags, numa_node, __builtin_return_address(0));
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100314}
315
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100316void *bpf_map_area_alloc(u64 size, int numa_node)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800317{
318 return __bpf_map_area_alloc(size, numa_node, false);
319}
320
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100321void *bpf_map_area_mmapable_alloc(u64 size, int numa_node)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800322{
323 return __bpf_map_area_alloc(size, numa_node, true);
324}
325
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100326void bpf_map_area_free(void *area)
327{
328 kvfree(area);
329}
330
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200331static u32 bpf_map_flags_retain_permanent(u32 flags)
332{
333 /* Some map creation flags are not tied to the map object but
334 * rather to the map fd instead, so they have no meaning upon
335 * map object inspection since multiple file descriptors with
336 * different (access) properties can exist here. Thus, given
337 * this has zero meaning for the map itself, lets clear these
338 * from here.
339 */
340 return flags & ~(BPF_F_RDONLY | BPF_F_WRONLY);
341}
342
Jakub Kicinskibd475642018-01-11 20:29:06 -0800343void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr)
344{
345 map->map_type = attr->map_type;
346 map->key_size = attr->key_size;
347 map->value_size = attr->value_size;
348 map->max_entries = attr->max_entries;
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200349 map->map_flags = bpf_map_flags_retain_permanent(attr->map_flags);
Jakub Kicinskibd475642018-01-11 20:29:06 -0800350 map->numa_node = bpf_map_attr_numa_node(attr);
351}
352
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700353static int bpf_charge_memlock(struct user_struct *user, u32 pages)
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700354{
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700355 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700356
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700357 if (atomic_long_add_return(pages, &user->locked_vm) > memlock_limit) {
358 atomic_long_sub(pages, &user->locked_vm);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700359 return -EPERM;
360 }
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700361 return 0;
362}
363
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700364static void bpf_uncharge_memlock(struct user_struct *user, u32 pages)
365{
Roman Gushchinb936ca62019-05-29 18:03:58 -0700366 if (user)
367 atomic_long_sub(pages, &user->locked_vm);
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700368}
369
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100370int bpf_map_charge_init(struct bpf_map_memory *mem, u64 size)
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700371{
Roman Gushchinc85d6912019-05-29 18:03:59 -0700372 u32 pages = round_up(size, PAGE_SIZE) >> PAGE_SHIFT;
373 struct user_struct *user;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700374 int ret;
375
Roman Gushchinc85d6912019-05-29 18:03:59 -0700376 if (size >= U32_MAX - PAGE_SIZE)
377 return -E2BIG;
378
379 user = get_current_user();
Roman Gushchinb936ca62019-05-29 18:03:58 -0700380 ret = bpf_charge_memlock(user, pages);
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700381 if (ret) {
382 free_uid(user);
383 return ret;
384 }
Roman Gushchinb936ca62019-05-29 18:03:58 -0700385
386 mem->pages = pages;
387 mem->user = user;
388
389 return 0;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700390}
391
Roman Gushchinb936ca62019-05-29 18:03:58 -0700392void bpf_map_charge_finish(struct bpf_map_memory *mem)
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700393{
Roman Gushchinb936ca62019-05-29 18:03:58 -0700394 bpf_uncharge_memlock(mem->user, mem->pages);
395 free_uid(mem->user);
396}
Roman Gushchin3539b962019-05-29 18:03:57 -0700397
Roman Gushchinb936ca62019-05-29 18:03:58 -0700398void bpf_map_charge_move(struct bpf_map_memory *dst,
399 struct bpf_map_memory *src)
400{
401 *dst = *src;
402
403 /* Make sure src will not be used for the redundant uncharging. */
404 memset(src, 0, sizeof(struct bpf_map_memory));
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700405}
406
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700407int bpf_map_charge_memlock(struct bpf_map *map, u32 pages)
408{
409 int ret;
410
Roman Gushchin3539b962019-05-29 18:03:57 -0700411 ret = bpf_charge_memlock(map->memory.user, pages);
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700412 if (ret)
413 return ret;
Roman Gushchin3539b962019-05-29 18:03:57 -0700414 map->memory.pages += pages;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700415 return ret;
416}
417
418void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages)
419{
Roman Gushchin3539b962019-05-29 18:03:57 -0700420 bpf_uncharge_memlock(map->memory.user, pages);
421 map->memory.pages -= pages;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700422}
423
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700424static int bpf_map_alloc_id(struct bpf_map *map)
425{
426 int id;
427
Shaohua Lib76354c2018-03-27 11:53:21 -0700428 idr_preload(GFP_KERNEL);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700429 spin_lock_bh(&map_idr_lock);
430 id = idr_alloc_cyclic(&map_idr, map, 1, INT_MAX, GFP_ATOMIC);
431 if (id > 0)
432 map->id = id;
433 spin_unlock_bh(&map_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -0700434 idr_preload_end();
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700435
436 if (WARN_ON_ONCE(!id))
437 return -ENOSPC;
438
439 return id > 0 ? 0 : id;
440}
441
Jakub Kicinskia3884572018-01-11 20:29:09 -0800442void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700443{
Eric Dumazet930651a2017-09-19 09:15:59 -0700444 unsigned long flags;
445
Jakub Kicinskia3884572018-01-11 20:29:09 -0800446 /* Offloaded maps are removed from the IDR store when their device
447 * disappears - even if someone holds an fd to them they are unusable,
448 * the memory is gone, all ops will fail; they are simply waiting for
449 * refcnt to drop to be freed.
450 */
451 if (!map->id)
452 return;
453
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700454 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700455 spin_lock_irqsave(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700456 else
457 __acquire(&map_idr_lock);
458
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700459 idr_remove(&map_idr, map->id);
Jakub Kicinskia3884572018-01-11 20:29:09 -0800460 map->id = 0;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700461
462 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700463 spin_unlock_irqrestore(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700464 else
465 __release(&map_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700466}
467
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700468/* called from workqueue */
469static void bpf_map_free_deferred(struct work_struct *work)
470{
471 struct bpf_map *map = container_of(work, struct bpf_map, work);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700472 struct bpf_map_memory mem;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700473
Roman Gushchinb936ca62019-05-29 18:03:58 -0700474 bpf_map_charge_move(&mem, &map->memory);
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700475 security_bpf_map_free(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700476 /* implementation dependent freeing */
477 map->ops->map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700478 bpf_map_charge_finish(&mem);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700479}
480
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100481static void bpf_map_put_uref(struct bpf_map *map)
482{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800483 if (atomic64_dec_and_test(&map->usercnt)) {
John Fastabendba6b8de2018-04-23 15:39:23 -0700484 if (map->ops->map_release_uref)
485 map->ops->map_release_uref(map);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100486 }
487}
488
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700489/* decrement map refcnt and schedule it for freeing via workqueue
490 * (unrelying map implementation ops->map_free() might sleep)
491 */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700492static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700493{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800494 if (atomic64_dec_and_test(&map->refcnt)) {
Martin KaFai Lau34ad5582017-06-05 12:15:48 -0700495 /* bpf_map_free_id() must be called first */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700496 bpf_map_free_id(map, do_idr_lock);
Martin KaFai Lau78958fc2018-05-04 14:49:51 -0700497 btf_put(map->btf);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700498 INIT_WORK(&map->work, bpf_map_free_deferred);
499 schedule_work(&map->work);
500 }
501}
502
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700503void bpf_map_put(struct bpf_map *map)
504{
505 __bpf_map_put(map, true);
506}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700507EXPORT_SYMBOL_GPL(bpf_map_put);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700508
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100509void bpf_map_put_with_uref(struct bpf_map *map)
510{
511 bpf_map_put_uref(map);
512 bpf_map_put(map);
513}
514
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700515static int bpf_map_release(struct inode *inode, struct file *filp)
516{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200517 struct bpf_map *map = filp->private_data;
518
519 if (map->ops->map_release)
520 map->ops->map_release(map, filp);
521
522 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700523 return 0;
524}
525
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200526static fmode_t map_get_sys_perms(struct bpf_map *map, struct fd f)
527{
528 fmode_t mode = f.file->f_mode;
529
530 /* Our file permissions may have been overridden by global
531 * map permissions facing syscall side.
532 */
533 if (READ_ONCE(map->frozen))
534 mode &= ~FMODE_CAN_WRITE;
535 return mode;
536}
537
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100538#ifdef CONFIG_PROC_FS
539static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
540{
541 const struct bpf_map *map = filp->private_data;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100542 const struct bpf_array *array;
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100543 u32 type = 0, jited = 0;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100544
545 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
546 array = container_of(map, struct bpf_array, map);
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100547 type = array->aux->type;
548 jited = array->aux->jited;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100549 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100550
551 seq_printf(m,
552 "map_type:\t%u\n"
553 "key_size:\t%u\n"
554 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100555 "max_entries:\t%u\n"
Daniel Borkmann21116b72016-11-26 01:28:07 +0100556 "map_flags:\t%#x\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +0200557 "memlock:\t%llu\n"
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200558 "map_id:\t%u\n"
559 "frozen:\t%u\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100560 map->map_type,
561 map->key_size,
562 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100563 map->max_entries,
Daniel Borkmann21116b72016-11-26 01:28:07 +0100564 map->map_flags,
Roman Gushchin3539b962019-05-29 18:03:57 -0700565 map->memory.pages * 1ULL << PAGE_SHIFT,
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200566 map->id,
567 READ_ONCE(map->frozen));
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100568 if (type) {
569 seq_printf(m, "owner_prog_type:\t%u\n", type);
570 seq_printf(m, "owner_jited:\t%u\n", jited);
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200571 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100572}
573#endif
574
Chenbo Feng6e71b042017-10-18 13:00:22 -0700575static ssize_t bpf_dummy_read(struct file *filp, char __user *buf, size_t siz,
576 loff_t *ppos)
577{
578 /* We need this handler such that alloc_file() enables
579 * f_mode with FMODE_CAN_READ.
580 */
581 return -EINVAL;
582}
583
584static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
585 size_t siz, loff_t *ppos)
586{
587 /* We need this handler such that alloc_file() enables
588 * f_mode with FMODE_CAN_WRITE.
589 */
590 return -EINVAL;
591}
592
Andrii Nakryikofc970222019-11-17 09:28:04 -0800593/* called for any extra memory-mapped regions (except initial) */
594static void bpf_map_mmap_open(struct vm_area_struct *vma)
595{
596 struct bpf_map *map = vma->vm_file->private_data;
597
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700598 if (vma->vm_flags & VM_MAYWRITE) {
Andrii Nakryikofc970222019-11-17 09:28:04 -0800599 mutex_lock(&map->freeze_mutex);
600 map->writecnt++;
601 mutex_unlock(&map->freeze_mutex);
602 }
603}
604
605/* called for all unmapped memory region (including initial) */
606static void bpf_map_mmap_close(struct vm_area_struct *vma)
607{
608 struct bpf_map *map = vma->vm_file->private_data;
609
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700610 if (vma->vm_flags & VM_MAYWRITE) {
Andrii Nakryikofc970222019-11-17 09:28:04 -0800611 mutex_lock(&map->freeze_mutex);
612 map->writecnt--;
613 mutex_unlock(&map->freeze_mutex);
614 }
Andrii Nakryikofc970222019-11-17 09:28:04 -0800615}
616
617static const struct vm_operations_struct bpf_map_default_vmops = {
618 .open = bpf_map_mmap_open,
619 .close = bpf_map_mmap_close,
620};
621
622static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
623{
624 struct bpf_map *map = filp->private_data;
625 int err;
626
627 if (!map->ops->map_mmap || map_value_has_spin_lock(map))
628 return -ENOTSUPP;
629
630 if (!(vma->vm_flags & VM_SHARED))
631 return -EINVAL;
632
633 mutex_lock(&map->freeze_mutex);
634
Andrii Nakryikodfeb3762020-05-18 22:38:24 -0700635 if (vma->vm_flags & VM_WRITE) {
636 if (map->frozen) {
637 err = -EPERM;
638 goto out;
639 }
640 /* map is meant to be read-only, so do not allow mapping as
641 * writable, because it's possible to leak a writable page
642 * reference and allows user-space to still modify it after
643 * freezing, while verifier will assume contents do not change
644 */
645 if (map->map_flags & BPF_F_RDONLY_PROG) {
646 err = -EACCES;
647 goto out;
648 }
Andrii Nakryikofc970222019-11-17 09:28:04 -0800649 }
650
651 /* set default open/close callbacks */
652 vma->vm_ops = &bpf_map_default_vmops;
653 vma->vm_private_data = map;
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700654 vma->vm_flags &= ~VM_MAYEXEC;
655 if (!(vma->vm_flags & VM_WRITE))
656 /* disallow re-mapping with PROT_WRITE */
657 vma->vm_flags &= ~VM_MAYWRITE;
Andrii Nakryikofc970222019-11-17 09:28:04 -0800658
659 err = map->ops->map_mmap(map, vma);
660 if (err)
661 goto out;
662
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700663 if (vma->vm_flags & VM_MAYWRITE)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800664 map->writecnt++;
665out:
666 mutex_unlock(&map->freeze_mutex);
667 return err;
668}
669
Andrii Nakryiko457f4432020-05-29 00:54:20 -0700670static __poll_t bpf_map_poll(struct file *filp, struct poll_table_struct *pts)
671{
672 struct bpf_map *map = filp->private_data;
673
674 if (map->ops->map_poll)
675 return map->ops->map_poll(map, filp, pts);
676
677 return EPOLLERR;
678}
679
Chenbo Fengf66e4482017-10-18 13:00:26 -0700680const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100681#ifdef CONFIG_PROC_FS
682 .show_fdinfo = bpf_map_show_fdinfo,
683#endif
684 .release = bpf_map_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700685 .read = bpf_dummy_read,
686 .write = bpf_dummy_write,
Andrii Nakryikofc970222019-11-17 09:28:04 -0800687 .mmap = bpf_map_mmap,
Andrii Nakryiko457f4432020-05-29 00:54:20 -0700688 .poll = bpf_map_poll,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700689};
690
Chenbo Feng6e71b042017-10-18 13:00:22 -0700691int bpf_map_new_fd(struct bpf_map *map, int flags)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100692{
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700693 int ret;
694
695 ret = security_bpf_map(map, OPEN_FMODE(flags));
696 if (ret < 0)
697 return ret;
698
Daniel Borkmannaa797812015-10-29 14:58:06 +0100699 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700700 flags | O_CLOEXEC);
701}
702
703int bpf_get_file_flag(int flags)
704{
705 if ((flags & BPF_F_RDONLY) && (flags & BPF_F_WRONLY))
706 return -EINVAL;
707 if (flags & BPF_F_RDONLY)
708 return O_RDONLY;
709 if (flags & BPF_F_WRONLY)
710 return O_WRONLY;
711 return O_RDWR;
Daniel Borkmannaa797812015-10-29 14:58:06 +0100712}
713
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700714/* helper macro to check that unused fields 'union bpf_attr' are zero */
715#define CHECK_ATTR(CMD) \
716 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
717 sizeof(attr->CMD##_LAST_FIELD), 0, \
718 sizeof(*attr) - \
719 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
720 sizeof(attr->CMD##_LAST_FIELD)) != NULL
721
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700722/* dst and src must have at least "size" number of bytes.
723 * Return strlen on success and < 0 on error.
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700724 */
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700725int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size)
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700726{
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700727 const char *end = src + size;
728 const char *orig_src = src;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700729
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700730 memset(dst, 0, size);
Daniel Borkmann3e0ddc4f2019-04-09 23:20:07 +0200731 /* Copy all isalnum(), '_' and '.' chars. */
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700732 while (src < end && *src) {
Daniel Borkmann3e0ddc4f2019-04-09 23:20:07 +0200733 if (!isalnum(*src) &&
734 *src != '_' && *src != '.')
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700735 return -EINVAL;
736 *dst++ = *src++;
737 }
738
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700739 /* No '\0' found in "size" number of bytes */
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700740 if (src == end)
741 return -EINVAL;
742
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700743 return src - orig_src;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700744}
745
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200746int map_check_no_btf(const struct bpf_map *map,
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800747 const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200748 const struct btf_type *key_type,
749 const struct btf_type *value_type)
750{
751 return -ENOTSUPP;
752}
753
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800754static int map_check_btf(struct bpf_map *map, const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200755 u32 btf_key_id, u32 btf_value_id)
756{
757 const struct btf_type *key_type, *value_type;
758 u32 key_size, value_size;
759 int ret = 0;
760
Daniel Borkmann2824ecb2019-04-09 23:20:10 +0200761 /* Some maps allow key to be unspecified. */
762 if (btf_key_id) {
763 key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
764 if (!key_type || key_size != map->key_size)
765 return -EINVAL;
766 } else {
767 key_type = btf_type_by_id(btf, 0);
768 if (!map->ops->map_check_btf)
769 return -EINVAL;
770 }
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200771
772 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
773 if (!value_type || value_size != map->value_size)
774 return -EINVAL;
775
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800776 map->spin_lock_off = btf_find_spin_lock(btf, value_type);
777
778 if (map_value_has_spin_lock(map)) {
Daniel Borkmann591fe982019-04-09 23:20:05 +0200779 if (map->map_flags & BPF_F_RDONLY_PROG)
780 return -EACCES;
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800781 if (map->map_type != BPF_MAP_TYPE_HASH &&
Alexei Starovoitove16d2f12019-01-31 15:40:05 -0800782 map->map_type != BPF_MAP_TYPE_ARRAY &&
Martin KaFai Lau6ac99e82019-04-26 16:39:39 -0700783 map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE &&
784 map->map_type != BPF_MAP_TYPE_SK_STORAGE)
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800785 return -ENOTSUPP;
786 if (map->spin_lock_off + sizeof(struct bpf_spin_lock) >
787 map->value_size) {
788 WARN_ONCE(1,
789 "verifier bug spin_lock_off %d value_size %d\n",
790 map->spin_lock_off, map->value_size);
791 return -EFAULT;
792 }
793 }
794
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200795 if (map->ops->map_check_btf)
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800796 ret = map->ops->map_check_btf(map, btf, key_type, value_type);
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200797
798 return ret;
799}
800
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800801#define BPF_MAP_CREATE_LAST_FIELD btf_vmlinux_value_type_id
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700802/* called via syscall */
803static int map_create(union bpf_attr *attr)
804{
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700805 int numa_node = bpf_map_attr_numa_node(attr);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700806 struct bpf_map_memory mem;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700807 struct bpf_map *map;
Chenbo Feng6e71b042017-10-18 13:00:22 -0700808 int f_flags;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700809 int err;
810
811 err = CHECK_ATTR(BPF_MAP_CREATE);
812 if (err)
813 return -EINVAL;
814
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800815 if (attr->btf_vmlinux_value_type_id) {
816 if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS ||
817 attr->btf_key_type_id || attr->btf_value_type_id)
818 return -EINVAL;
819 } else if (attr->btf_key_type_id && !attr->btf_value_type_id) {
820 return -EINVAL;
821 }
822
Chenbo Feng6e71b042017-10-18 13:00:22 -0700823 f_flags = bpf_get_file_flag(attr->map_flags);
824 if (f_flags < 0)
825 return f_flags;
826
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700827 if (numa_node != NUMA_NO_NODE &&
Eric Dumazet96e5ae42017-09-04 22:41:02 -0700828 ((unsigned int)numa_node >= nr_node_ids ||
829 !node_online(numa_node)))
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700830 return -EINVAL;
831
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700832 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
833 map = find_and_alloc_map(attr);
834 if (IS_ERR(map))
835 return PTR_ERR(map);
836
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700837 err = bpf_obj_name_cpy(map->name, attr->map_name,
838 sizeof(attr->map_name));
839 if (err < 0)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700840 goto free_map;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -0700841
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800842 atomic64_set(&map->refcnt, 1);
843 atomic64_set(&map->usercnt, 1);
Andrii Nakryikofc970222019-11-17 09:28:04 -0800844 mutex_init(&map->freeze_mutex);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700845
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800846 map->spin_lock_off = -EINVAL;
847 if (attr->btf_key_type_id || attr->btf_value_type_id ||
848 /* Even the map's value is a kernel's struct,
849 * the bpf_prog.o must have BTF to begin with
850 * to figure out the corresponding kernel's
851 * counter part. Thus, attr->btf_fd has
852 * to be valid also.
853 */
854 attr->btf_vmlinux_value_type_id) {
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700855 struct btf *btf;
856
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700857 btf = btf_get_by_fd(attr->btf_fd);
858 if (IS_ERR(btf)) {
859 err = PTR_ERR(btf);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700860 goto free_map;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700861 }
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800862 map->btf = btf;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700863
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800864 if (attr->btf_value_type_id) {
865 err = map_check_btf(map, btf, attr->btf_key_type_id,
866 attr->btf_value_type_id);
867 if (err)
868 goto free_map;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700869 }
870
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -0700871 map->btf_key_type_id = attr->btf_key_type_id;
872 map->btf_value_type_id = attr->btf_value_type_id;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800873 map->btf_vmlinux_value_type_id =
874 attr->btf_vmlinux_value_type_id;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700875 }
876
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700877 err = security_bpf_map_alloc(map);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700878 if (err)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700879 goto free_map;
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700880
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700881 err = bpf_map_alloc_id(map);
882 if (err)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700883 goto free_map_sec;
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700884
Chenbo Feng6e71b042017-10-18 13:00:22 -0700885 err = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700886 if (err < 0) {
887 /* failed to allocate fd.
Peng Sun352d20d2019-02-27 22:36:25 +0800888 * bpf_map_put_with_uref() is needed because the above
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700889 * bpf_map_alloc_id() has published the map
890 * to the userspace and the userspace may
891 * have refcnt-ed it through BPF_MAP_GET_FD_BY_ID.
892 */
Peng Sun352d20d2019-02-27 22:36:25 +0800893 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700894 return err;
895 }
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700896
897 return err;
898
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700899free_map_sec:
900 security_bpf_map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700901free_map:
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700902 btf_put(map->btf);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700903 bpf_map_charge_move(&mem, &map->memory);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700904 map->ops->map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700905 bpf_map_charge_finish(&mem);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700906 return err;
907}
908
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700909/* if error is returned, fd is released.
910 * On success caller should complete fd access with matching fdput()
911 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100912struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700913{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700914 if (!f.file)
915 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700916 if (f.file->f_op != &bpf_map_fops) {
917 fdput(f);
918 return ERR_PTR(-EINVAL);
919 }
920
Daniel Borkmannc2101292015-10-29 14:58:07 +0100921 return f.file->private_data;
922}
923
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800924void bpf_map_inc(struct bpf_map *map)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100925{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800926 atomic64_inc(&map->refcnt);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100927}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700928EXPORT_SYMBOL_GPL(bpf_map_inc);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100929
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800930void bpf_map_inc_with_uref(struct bpf_map *map)
931{
932 atomic64_inc(&map->refcnt);
933 atomic64_inc(&map->usercnt);
934}
935EXPORT_SYMBOL_GPL(bpf_map_inc_with_uref);
936
Martin KaFai Lau1ed4d922020-02-25 15:04:21 -0800937struct bpf_map *bpf_map_get(u32 ufd)
938{
939 struct fd f = fdget(ufd);
940 struct bpf_map *map;
941
942 map = __bpf_map_get(f);
943 if (IS_ERR(map))
944 return map;
945
946 bpf_map_inc(map);
947 fdput(f);
948
949 return map;
950}
951
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100952struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +0100953{
954 struct fd f = fdget(ufd);
955 struct bpf_map *map;
956
957 map = __bpf_map_get(f);
958 if (IS_ERR(map))
959 return map;
960
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800961 bpf_map_inc_with_uref(map);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100962 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700963
964 return map;
965}
966
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700967/* map_idr_lock should have been held */
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800968static struct bpf_map *__bpf_map_inc_not_zero(struct bpf_map *map, bool uref)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700969{
970 int refold;
971
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800972 refold = atomic64_fetch_add_unless(&map->refcnt, 1, 0);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700973 if (!refold)
974 return ERR_PTR(-ENOENT);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700975 if (uref)
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800976 atomic64_inc(&map->usercnt);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700977
978 return map;
979}
980
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800981struct bpf_map *bpf_map_inc_not_zero(struct bpf_map *map)
Stanislav Fomichevb0e47012019-08-14 10:37:48 -0700982{
983 spin_lock_bh(&map_idr_lock);
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800984 map = __bpf_map_inc_not_zero(map, false);
Stanislav Fomichevb0e47012019-08-14 10:37:48 -0700985 spin_unlock_bh(&map_idr_lock);
986
987 return map;
988}
989EXPORT_SYMBOL_GPL(bpf_map_inc_not_zero);
990
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -0800991int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
992{
993 return -ENOTSUPP;
994}
995
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +0200996static void *__bpf_copy_key(void __user *ukey, u64 key_size)
997{
998 if (key_size)
999 return memdup_user(ukey, key_size);
1000
1001 if (ukey)
1002 return ERR_PTR(-EINVAL);
1003
1004 return NULL;
1005}
1006
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001007/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001008#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001009
1010static int map_lookup_elem(union bpf_attr *attr)
1011{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001012 void __user *ukey = u64_to_user_ptr(attr->key);
1013 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001014 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001015 struct bpf_map *map;
Brian Vazquez15c14a32020-01-15 10:43:00 -08001016 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001017 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001018 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001019 int err;
1020
1021 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
1022 return -EINVAL;
1023
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001024 if (attr->flags & ~BPF_F_LOCK)
1025 return -EINVAL;
1026
Daniel Borkmann592867b2015-09-08 18:00:09 +02001027 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001028 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001029 if (IS_ERR(map))
1030 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001031 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001032 err = -EPERM;
1033 goto err_put;
1034 }
1035
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001036 if ((attr->flags & BPF_F_LOCK) &&
1037 !map_value_has_spin_lock(map)) {
1038 err = -EINVAL;
1039 goto err_put;
1040 }
1041
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001042 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001043 if (IS_ERR(key)) {
1044 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001045 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001046 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001047
Brian Vazquez15c14a32020-01-15 10:43:00 -08001048 value_size = bpf_map_value_size(map);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001049
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001050 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001051 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001052 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001053 goto free_key;
1054
Brian Vazquez15c14a32020-01-15 10:43:00 -08001055 err = bpf_map_copy_value(map, key, value, attr->flags);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001056 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001057 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001058
1059 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001060 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001061 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001062
1063 err = 0;
1064
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001065free_value:
1066 kfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001067free_key:
1068 kfree(key);
1069err_put:
1070 fdput(f);
1071 return err;
1072}
1073
Daniel Colascione1ae80cf2018-10-12 03:54:27 -07001074
Alexei Starovoitov3274f522014-11-13 17:36:44 -08001075#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001076
1077static int map_update_elem(union bpf_attr *attr)
1078{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001079 void __user *ukey = u64_to_user_ptr(attr->key);
1080 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001081 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001082 struct bpf_map *map;
1083 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001084 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001085 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001086 int err;
1087
1088 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
1089 return -EINVAL;
1090
Daniel Borkmann592867b2015-09-08 18:00:09 +02001091 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001092 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001093 if (IS_ERR(map))
1094 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001095 if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001096 err = -EPERM;
1097 goto err_put;
1098 }
1099
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001100 if ((attr->flags & BPF_F_LOCK) &&
1101 !map_value_has_spin_lock(map)) {
1102 err = -EINVAL;
1103 goto err_put;
1104 }
1105
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001106 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001107 if (IS_ERR(key)) {
1108 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001109 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001110 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001111
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001112 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -08001113 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Roman Gushchinb741f162018-09-28 14:45:43 +00001114 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
1115 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001116 value_size = round_up(map->value_size, 8) * num_possible_cpus();
1117 else
1118 value_size = map->value_size;
1119
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001120 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001121 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001122 if (!value)
1123 goto free_key;
1124
1125 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001126 if (copy_from_user(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001127 goto free_value;
1128
Brian Vazquez15c14a32020-01-15 10:43:00 -08001129 err = bpf_map_update_value(map, f, key, value, attr->flags);
Jesper Dangaard Brouer6710e112017-10-16 12:19:28 +02001130
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001131free_value:
1132 kfree(value);
1133free_key:
1134 kfree(key);
1135err_put:
1136 fdput(f);
1137 return err;
1138}
1139
1140#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
1141
1142static int map_delete_elem(union bpf_attr *attr)
1143{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001144 void __user *ukey = u64_to_user_ptr(attr->key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001145 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001146 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001147 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001148 void *key;
1149 int err;
1150
1151 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
1152 return -EINVAL;
1153
Daniel Borkmann592867b2015-09-08 18:00:09 +02001154 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001155 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001156 if (IS_ERR(map))
1157 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001158 if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001159 err = -EPERM;
1160 goto err_put;
1161 }
1162
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001163 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001164 if (IS_ERR(key)) {
1165 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001166 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001167 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001168
Jakub Kicinskia3884572018-01-11 20:29:09 -08001169 if (bpf_map_is_dev_bound(map)) {
1170 err = bpf_map_offload_delete_elem(map, key);
1171 goto out;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -08001172 } else if (IS_FD_PROG_ARRAY(map) ||
1173 map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
1174 /* These maps require sleepable context */
Daniel Borkmannda765a22019-11-22 21:07:58 +01001175 err = map->ops->map_delete_elem(map, key);
1176 goto out;
Jakub Kicinskia3884572018-01-11 20:29:09 -08001177 }
1178
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001179 bpf_disable_instrumentation();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001180 rcu_read_lock();
1181 err = map->ops->map_delete_elem(map, key);
1182 rcu_read_unlock();
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001183 bpf_enable_instrumentation();
Daniel Colascione1ae80cf2018-10-12 03:54:27 -07001184 maybe_wait_bpf_programs(map);
Jakub Kicinskia3884572018-01-11 20:29:09 -08001185out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001186 kfree(key);
1187err_put:
1188 fdput(f);
1189 return err;
1190}
1191
1192/* last field in 'union bpf_attr' used by this command */
1193#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
1194
1195static int map_get_next_key(union bpf_attr *attr)
1196{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001197 void __user *ukey = u64_to_user_ptr(attr->key);
1198 void __user *unext_key = u64_to_user_ptr(attr->next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001199 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001200 struct bpf_map *map;
1201 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001202 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001203 int err;
1204
1205 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
1206 return -EINVAL;
1207
Daniel Borkmann592867b2015-09-08 18:00:09 +02001208 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001209 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001210 if (IS_ERR(map))
1211 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001212 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001213 err = -EPERM;
1214 goto err_put;
1215 }
1216
Teng Qin8fe45922017-04-24 19:00:37 -07001217 if (ukey) {
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001218 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001219 if (IS_ERR(key)) {
1220 err = PTR_ERR(key);
Teng Qin8fe45922017-04-24 19:00:37 -07001221 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001222 }
Teng Qin8fe45922017-04-24 19:00:37 -07001223 } else {
1224 key = NULL;
1225 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001226
1227 err = -ENOMEM;
1228 next_key = kmalloc(map->key_size, GFP_USER);
1229 if (!next_key)
1230 goto free_key;
1231
Jakub Kicinskia3884572018-01-11 20:29:09 -08001232 if (bpf_map_is_dev_bound(map)) {
1233 err = bpf_map_offload_get_next_key(map, key, next_key);
1234 goto out;
1235 }
1236
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001237 rcu_read_lock();
1238 err = map->ops->map_get_next_key(map, key, next_key);
1239 rcu_read_unlock();
Jakub Kicinskia3884572018-01-11 20:29:09 -08001240out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001241 if (err)
1242 goto free_next_key;
1243
1244 err = -EFAULT;
1245 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
1246 goto free_next_key;
1247
1248 err = 0;
1249
1250free_next_key:
1251 kfree(next_key);
1252free_key:
1253 kfree(key);
1254err_put:
1255 fdput(f);
1256 return err;
1257}
1258
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001259int generic_map_delete_batch(struct bpf_map *map,
1260 const union bpf_attr *attr,
1261 union bpf_attr __user *uattr)
1262{
1263 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1264 u32 cp, max_count;
1265 int err = 0;
1266 void *key;
1267
1268 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1269 return -EINVAL;
1270
1271 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1272 !map_value_has_spin_lock(map)) {
1273 return -EINVAL;
1274 }
1275
1276 max_count = attr->batch.count;
1277 if (!max_count)
1278 return 0;
1279
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001280 key = kmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
1281 if (!key)
1282 return -ENOMEM;
1283
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001284 for (cp = 0; cp < max_count; cp++) {
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001285 err = -EFAULT;
1286 if (copy_from_user(key, keys + cp * map->key_size,
1287 map->key_size))
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001288 break;
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001289
1290 if (bpf_map_is_dev_bound(map)) {
1291 err = bpf_map_offload_delete_elem(map, key);
1292 break;
1293 }
1294
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001295 bpf_disable_instrumentation();
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001296 rcu_read_lock();
1297 err = map->ops->map_delete_elem(map, key);
1298 rcu_read_unlock();
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001299 bpf_enable_instrumentation();
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001300 maybe_wait_bpf_programs(map);
1301 if (err)
1302 break;
1303 }
1304 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
1305 err = -EFAULT;
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001306
1307 kfree(key);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001308 return err;
1309}
1310
1311int generic_map_update_batch(struct bpf_map *map,
1312 const union bpf_attr *attr,
1313 union bpf_attr __user *uattr)
1314{
1315 void __user *values = u64_to_user_ptr(attr->batch.values);
1316 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1317 u32 value_size, cp, max_count;
1318 int ufd = attr->map_fd;
1319 void *key, *value;
1320 struct fd f;
1321 int err = 0;
1322
1323 f = fdget(ufd);
1324 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1325 return -EINVAL;
1326
1327 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1328 !map_value_has_spin_lock(map)) {
1329 return -EINVAL;
1330 }
1331
1332 value_size = bpf_map_value_size(map);
1333
1334 max_count = attr->batch.count;
1335 if (!max_count)
1336 return 0;
1337
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001338 key = kmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
1339 if (!key)
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001340 return -ENOMEM;
1341
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001342 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
1343 if (!value) {
1344 kfree(key);
1345 return -ENOMEM;
1346 }
1347
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001348 for (cp = 0; cp < max_count; cp++) {
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001349 err = -EFAULT;
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001350 if (copy_from_user(key, keys + cp * map->key_size,
1351 map->key_size) ||
1352 copy_from_user(value, values + cp * value_size, value_size))
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001353 break;
1354
1355 err = bpf_map_update_value(map, f, key, value,
1356 attr->batch.elem_flags);
1357
1358 if (err)
1359 break;
1360 }
1361
1362 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
1363 err = -EFAULT;
1364
1365 kfree(value);
1366 kfree(key);
1367 return err;
1368}
1369
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001370#define MAP_LOOKUP_RETRIES 3
1371
1372int generic_map_lookup_batch(struct bpf_map *map,
1373 const union bpf_attr *attr,
1374 union bpf_attr __user *uattr)
1375{
1376 void __user *uobatch = u64_to_user_ptr(attr->batch.out_batch);
1377 void __user *ubatch = u64_to_user_ptr(attr->batch.in_batch);
1378 void __user *values = u64_to_user_ptr(attr->batch.values);
1379 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1380 void *buf, *buf_prevkey, *prev_key, *key, *value;
1381 int err, retry = MAP_LOOKUP_RETRIES;
1382 u32 value_size, cp, max_count;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001383
1384 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1385 return -EINVAL;
1386
1387 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1388 !map_value_has_spin_lock(map))
1389 return -EINVAL;
1390
1391 value_size = bpf_map_value_size(map);
1392
1393 max_count = attr->batch.count;
1394 if (!max_count)
1395 return 0;
1396
1397 if (put_user(0, &uattr->batch.count))
1398 return -EFAULT;
1399
1400 buf_prevkey = kmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
1401 if (!buf_prevkey)
1402 return -ENOMEM;
1403
1404 buf = kmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN);
1405 if (!buf) {
Denis Efremovbb2359f2020-06-01 19:28:14 +03001406 kfree(buf_prevkey);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001407 return -ENOMEM;
1408 }
1409
1410 err = -EFAULT;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001411 prev_key = NULL;
1412 if (ubatch && copy_from_user(buf_prevkey, ubatch, map->key_size))
1413 goto free_buf;
1414 key = buf;
1415 value = key + map->key_size;
1416 if (ubatch)
1417 prev_key = buf_prevkey;
1418
1419 for (cp = 0; cp < max_count;) {
1420 rcu_read_lock();
1421 err = map->ops->map_get_next_key(map, prev_key, key);
1422 rcu_read_unlock();
1423 if (err)
1424 break;
1425 err = bpf_map_copy_value(map, key, value,
1426 attr->batch.elem_flags);
1427
1428 if (err == -ENOENT) {
1429 if (retry) {
1430 retry--;
1431 continue;
1432 }
1433 err = -EINTR;
1434 break;
1435 }
1436
1437 if (err)
1438 goto free_buf;
1439
1440 if (copy_to_user(keys + cp * map->key_size, key,
1441 map->key_size)) {
1442 err = -EFAULT;
1443 goto free_buf;
1444 }
1445 if (copy_to_user(values + cp * value_size, value, value_size)) {
1446 err = -EFAULT;
1447 goto free_buf;
1448 }
1449
1450 if (!prev_key)
1451 prev_key = buf_prevkey;
1452
1453 swap(prev_key, key);
1454 retry = MAP_LOOKUP_RETRIES;
1455 cp++;
1456 }
1457
1458 if (err == -EFAULT)
1459 goto free_buf;
1460
1461 if ((copy_to_user(&uattr->batch.count, &cp, sizeof(cp)) ||
1462 (cp && copy_to_user(uobatch, prev_key, map->key_size))))
1463 err = -EFAULT;
1464
1465free_buf:
1466 kfree(buf_prevkey);
1467 kfree(buf);
1468 return err;
1469}
1470
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001471#define BPF_MAP_LOOKUP_AND_DELETE_ELEM_LAST_FIELD value
1472
1473static int map_lookup_and_delete_elem(union bpf_attr *attr)
1474{
1475 void __user *ukey = u64_to_user_ptr(attr->key);
1476 void __user *uvalue = u64_to_user_ptr(attr->value);
1477 int ufd = attr->map_fd;
1478 struct bpf_map *map;
Alexei Starovoitov540fefc2018-10-19 13:52:38 -07001479 void *key, *value;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001480 u32 value_size;
1481 struct fd f;
1482 int err;
1483
1484 if (CHECK_ATTR(BPF_MAP_LOOKUP_AND_DELETE_ELEM))
1485 return -EINVAL;
1486
1487 f = fdget(ufd);
1488 map = __bpf_map_get(f);
1489 if (IS_ERR(map))
1490 return PTR_ERR(map);
Anton Protopopov1ea0f912020-05-27 18:56:59 +00001491 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) ||
1492 !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001493 err = -EPERM;
1494 goto err_put;
1495 }
1496
1497 key = __bpf_copy_key(ukey, map->key_size);
1498 if (IS_ERR(key)) {
1499 err = PTR_ERR(key);
1500 goto err_put;
1501 }
1502
1503 value_size = map->value_size;
1504
1505 err = -ENOMEM;
1506 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
1507 if (!value)
1508 goto free_key;
1509
1510 if (map->map_type == BPF_MAP_TYPE_QUEUE ||
1511 map->map_type == BPF_MAP_TYPE_STACK) {
1512 err = map->ops->map_pop_elem(map, value);
1513 } else {
1514 err = -ENOTSUPP;
1515 }
1516
1517 if (err)
1518 goto free_value;
1519
Wei Yongjun7f645462020-04-30 08:18:51 +00001520 if (copy_to_user(uvalue, value, value_size) != 0) {
1521 err = -EFAULT;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001522 goto free_value;
Wei Yongjun7f645462020-04-30 08:18:51 +00001523 }
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001524
1525 err = 0;
1526
1527free_value:
1528 kfree(value);
1529free_key:
1530 kfree(key);
1531err_put:
1532 fdput(f);
1533 return err;
1534}
1535
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001536#define BPF_MAP_FREEZE_LAST_FIELD map_fd
1537
1538static int map_freeze(const union bpf_attr *attr)
1539{
1540 int err = 0, ufd = attr->map_fd;
1541 struct bpf_map *map;
1542 struct fd f;
1543
1544 if (CHECK_ATTR(BPF_MAP_FREEZE))
1545 return -EINVAL;
1546
1547 f = fdget(ufd);
1548 map = __bpf_map_get(f);
1549 if (IS_ERR(map))
1550 return PTR_ERR(map);
Andrii Nakryikofc970222019-11-17 09:28:04 -08001551
Martin KaFai Lau849b4d92020-03-04 17:34:54 -08001552 if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
1553 fdput(f);
1554 return -ENOTSUPP;
1555 }
1556
Andrii Nakryikofc970222019-11-17 09:28:04 -08001557 mutex_lock(&map->freeze_mutex);
1558
1559 if (map->writecnt) {
1560 err = -EBUSY;
1561 goto err_put;
1562 }
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001563 if (READ_ONCE(map->frozen)) {
1564 err = -EBUSY;
1565 goto err_put;
1566 }
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07001567 if (!bpf_capable()) {
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001568 err = -EPERM;
1569 goto err_put;
1570 }
1571
1572 WRITE_ONCE(map->frozen, true);
1573err_put:
Andrii Nakryikofc970222019-11-17 09:28:04 -08001574 mutex_unlock(&map->freeze_mutex);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001575 fdput(f);
1576 return err;
1577}
1578
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001579static const struct bpf_prog_ops * const bpf_prog_types[] = {
Alexei Starovoitov91cc1a92019-11-14 10:57:15 -08001580#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001581 [_id] = & _name ## _prog_ops,
1582#define BPF_MAP_TYPE(_id, _ops)
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07001583#define BPF_LINK_TYPE(_id, _name)
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001584#include <linux/bpf_types.h>
1585#undef BPF_PROG_TYPE
1586#undef BPF_MAP_TYPE
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07001587#undef BPF_LINK_TYPE
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001588};
1589
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001590static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
1591{
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001592 const struct bpf_prog_ops *ops;
1593
1594 if (type >= ARRAY_SIZE(bpf_prog_types))
1595 return -EINVAL;
1596 type = array_index_nospec(type, ARRAY_SIZE(bpf_prog_types));
1597 ops = bpf_prog_types[type];
1598 if (!ops)
Johannes Bergbe9370a2017-04-11 15:34:57 +02001599 return -EINVAL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001600
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001601 if (!bpf_prog_is_dev_bound(prog->aux))
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001602 prog->aux->ops = ops;
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001603 else
1604 prog->aux->ops = &bpf_offload_prog_ops;
Johannes Bergbe9370a2017-04-11 15:34:57 +02001605 prog->type = type;
1606 return 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001607}
1608
Daniel Borkmannbae141f2019-12-06 22:49:34 +01001609enum bpf_audit {
1610 BPF_AUDIT_LOAD,
1611 BPF_AUDIT_UNLOAD,
1612 BPF_AUDIT_MAX,
1613};
1614
1615static const char * const bpf_audit_str[BPF_AUDIT_MAX] = {
1616 [BPF_AUDIT_LOAD] = "LOAD",
1617 [BPF_AUDIT_UNLOAD] = "UNLOAD",
1618};
1619
1620static void bpf_audit_prog(const struct bpf_prog *prog, unsigned int op)
1621{
1622 struct audit_context *ctx = NULL;
1623 struct audit_buffer *ab;
1624
1625 if (WARN_ON_ONCE(op >= BPF_AUDIT_MAX))
1626 return;
1627 if (audit_enabled == AUDIT_OFF)
1628 return;
1629 if (op == BPF_AUDIT_LOAD)
1630 ctx = audit_context();
1631 ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_BPF);
1632 if (unlikely(!ab))
1633 return;
1634 audit_log_format(ab, "prog-id=%u op=%s",
1635 prog->aux->id, bpf_audit_str[op]);
1636 audit_log_end(ab);
1637}
1638
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001639int __bpf_prog_charge(struct user_struct *user, u32 pages)
1640{
1641 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
1642 unsigned long user_bufs;
1643
1644 if (user) {
1645 user_bufs = atomic_long_add_return(pages, &user->locked_vm);
1646 if (user_bufs > memlock_limit) {
1647 atomic_long_sub(pages, &user->locked_vm);
1648 return -EPERM;
1649 }
1650 }
1651
1652 return 0;
1653}
1654
1655void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
1656{
1657 if (user)
1658 atomic_long_sub(pages, &user->locked_vm);
1659}
1660
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001661static int bpf_prog_charge_memlock(struct bpf_prog *prog)
1662{
1663 struct user_struct *user = get_current_user();
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001664 int ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001665
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001666 ret = __bpf_prog_charge(user, prog->pages);
1667 if (ret) {
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001668 free_uid(user);
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001669 return ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001670 }
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001671
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001672 prog->aux->user = user;
1673 return 0;
1674}
1675
1676static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
1677{
1678 struct user_struct *user = prog->aux->user;
1679
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001680 __bpf_prog_uncharge(user, prog->pages);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001681 free_uid(user);
1682}
1683
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001684static int bpf_prog_alloc_id(struct bpf_prog *prog)
1685{
1686 int id;
1687
Shaohua Lib76354c2018-03-27 11:53:21 -07001688 idr_preload(GFP_KERNEL);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001689 spin_lock_bh(&prog_idr_lock);
1690 id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
1691 if (id > 0)
1692 prog->aux->id = id;
1693 spin_unlock_bh(&prog_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -07001694 idr_preload_end();
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001695
1696 /* id is in [1, INT_MAX) */
1697 if (WARN_ON_ONCE(!id))
1698 return -ENOSPC;
1699
1700 return id > 0 ? 0 : id;
1701}
1702
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001703void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001704{
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001705 /* cBPF to eBPF migrations are currently not in the idr store.
1706 * Offloaded programs are removed from the store when their device
1707 * disappears - even if someone grabs an fd to them they are unusable,
1708 * simply waiting for refcnt to drop to be freed.
1709 */
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001710 if (!prog->aux->id)
1711 return;
1712
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001713 if (do_idr_lock)
1714 spin_lock_bh(&prog_idr_lock);
1715 else
1716 __acquire(&prog_idr_lock);
1717
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001718 idr_remove(&prog_idr, prog->aux->id);
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001719 prog->aux->id = 0;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001720
1721 if (do_idr_lock)
1722 spin_unlock_bh(&prog_idr_lock);
1723 else
1724 __release(&prog_idr_lock);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001725}
1726
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001727static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001728{
1729 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
1730
Daniel Borkmann3b4d9eb2019-10-22 23:30:38 +02001731 kvfree(aux->func_info);
Alexei Starovoitov8c1b6e62019-11-14 10:57:16 -08001732 kfree(aux->func_info_aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001733 bpf_prog_uncharge_memlock(aux->prog);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001734 security_bpf_prog_free(aux);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001735 bpf_prog_free(aux->prog);
1736}
1737
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001738static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred)
1739{
1740 bpf_prog_kallsyms_del_all(prog);
1741 btf_put(prog->aux->btf);
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001742 bpf_prog_free_linfo(prog);
1743
1744 if (deferred)
1745 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1746 else
1747 __bpf_prog_put_rcu(&prog->aux->rcu);
1748}
1749
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001750static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001751{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001752 if (atomic64_dec_and_test(&prog->aux->refcnt)) {
Song Liu6ee52e22019-01-17 08:15:15 -08001753 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
Daniel Borkmannbae141f2019-12-06 22:49:34 +01001754 bpf_audit_prog(prog, BPF_AUDIT_UNLOAD);
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001755 /* bpf_prog_free_id() must be called first */
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001756 bpf_prog_free_id(prog, do_idr_lock);
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001757 __bpf_prog_put_noref(prog, true);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01001758 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001759}
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001760
1761void bpf_prog_put(struct bpf_prog *prog)
1762{
1763 __bpf_prog_put(prog, true);
1764}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +01001765EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001766
1767static int bpf_prog_release(struct inode *inode, struct file *filp)
1768{
1769 struct bpf_prog *prog = filp->private_data;
1770
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001771 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001772 return 0;
1773}
1774
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001775static void bpf_prog_get_stats(const struct bpf_prog *prog,
1776 struct bpf_prog_stats *stats)
1777{
1778 u64 nsecs = 0, cnt = 0;
1779 int cpu;
1780
1781 for_each_possible_cpu(cpu) {
1782 const struct bpf_prog_stats *st;
1783 unsigned int start;
1784 u64 tnsecs, tcnt;
1785
1786 st = per_cpu_ptr(prog->aux->stats, cpu);
1787 do {
1788 start = u64_stats_fetch_begin_irq(&st->syncp);
1789 tnsecs = st->nsecs;
1790 tcnt = st->cnt;
1791 } while (u64_stats_fetch_retry_irq(&st->syncp, start));
1792 nsecs += tnsecs;
1793 cnt += tcnt;
1794 }
1795 stats->nsecs = nsecs;
1796 stats->cnt = cnt;
1797}
1798
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001799#ifdef CONFIG_PROC_FS
1800static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
1801{
1802 const struct bpf_prog *prog = filp->private_data;
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001803 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001804 struct bpf_prog_stats stats;
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001805
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001806 bpf_prog_get_stats(prog, &stats);
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001807 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001808 seq_printf(m,
1809 "prog_type:\t%u\n"
1810 "prog_jited:\t%u\n"
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001811 "prog_tag:\t%s\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +02001812 "memlock:\t%llu\n"
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001813 "prog_id:\t%u\n"
1814 "run_time_ns:\t%llu\n"
1815 "run_cnt:\t%llu\n",
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001816 prog->type,
1817 prog->jited,
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001818 prog_tag,
Daniel Borkmann4316b402018-06-02 23:06:34 +02001819 prog->pages * 1ULL << PAGE_SHIFT,
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001820 prog->aux->id,
1821 stats.nsecs,
1822 stats.cnt);
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001823}
1824#endif
1825
Chenbo Fengf66e4482017-10-18 13:00:26 -07001826const struct file_operations bpf_prog_fops = {
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001827#ifdef CONFIG_PROC_FS
1828 .show_fdinfo = bpf_prog_show_fdinfo,
1829#endif
1830 .release = bpf_prog_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -07001831 .read = bpf_dummy_read,
1832 .write = bpf_dummy_write,
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001833};
1834
Daniel Borkmannb2197752015-10-29 14:58:09 +01001835int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +01001836{
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001837 int ret;
1838
1839 ret = security_bpf_prog(prog);
1840 if (ret < 0)
1841 return ret;
1842
Daniel Borkmannaa797812015-10-29 14:58:06 +01001843 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
1844 O_RDWR | O_CLOEXEC);
1845}
1846
Daniel Borkmann113214b2016-06-30 17:24:44 +02001847static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001848{
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001849 if (!f.file)
1850 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001851 if (f.file->f_op != &bpf_prog_fops) {
1852 fdput(f);
1853 return ERR_PTR(-EINVAL);
1854 }
1855
Daniel Borkmannc2101292015-10-29 14:58:07 +01001856 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001857}
1858
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001859void bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001860{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001861 atomic64_add(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001862}
Brenden Blanco59d36562016-07-19 12:16:46 -07001863EXPORT_SYMBOL_GPL(bpf_prog_add);
1864
Daniel Borkmannc5405942016-11-09 22:02:34 +01001865void bpf_prog_sub(struct bpf_prog *prog, int i)
1866{
1867 /* Only to be used for undoing previous bpf_prog_add() in some
1868 * error path. We still know that another entity in our call
1869 * path holds a reference to the program, thus atomic_sub() can
1870 * be safely used in such cases!
1871 */
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001872 WARN_ON(atomic64_sub_return(i, &prog->aux->refcnt) == 0);
Daniel Borkmannc5405942016-11-09 22:02:34 +01001873}
1874EXPORT_SYMBOL_GPL(bpf_prog_sub);
1875
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001876void bpf_prog_inc(struct bpf_prog *prog)
Brenden Blanco59d36562016-07-19 12:16:46 -07001877{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001878 atomic64_inc(&prog->aux->refcnt);
Brenden Blanco59d36562016-07-19 12:16:46 -07001879}
Daniel Borkmann97bc4022016-11-19 01:45:00 +01001880EXPORT_SYMBOL_GPL(bpf_prog_inc);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001881
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001882/* prog_idr_lock should have been held */
John Fastabenda6f6df62017-08-15 22:32:22 -07001883struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001884{
1885 int refold;
1886
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001887 refold = atomic64_fetch_add_unless(&prog->aux->refcnt, 1, 0);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001888
1889 if (!refold)
1890 return ERR_PTR(-ENOENT);
1891
1892 return prog;
1893}
John Fastabenda6f6df62017-08-15 22:32:22 -07001894EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001895
Al Viro040ee692017-12-02 20:20:38 -05001896bool bpf_prog_get_ok(struct bpf_prog *prog,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001897 enum bpf_prog_type *attach_type, bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001898{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001899 /* not an attachment, just a refcount inc, always allow */
1900 if (!attach_type)
1901 return true;
Jakub Kicinski248f3462017-11-03 13:56:20 -07001902
1903 if (prog->type != *attach_type)
1904 return false;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001905 if (bpf_prog_is_dev_bound(prog->aux) && !attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001906 return false;
1907
1908 return true;
1909}
1910
1911static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001912 bool attach_drv)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001913{
1914 struct fd f = fdget(ufd);
1915 struct bpf_prog *prog;
1916
Daniel Borkmann113214b2016-06-30 17:24:44 +02001917 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001918 if (IS_ERR(prog))
1919 return prog;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001920 if (!bpf_prog_get_ok(prog, attach_type, attach_drv)) {
Daniel Borkmann113214b2016-06-30 17:24:44 +02001921 prog = ERR_PTR(-EINVAL);
1922 goto out;
1923 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001924
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001925 bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001926out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001927 fdput(f);
1928 return prog;
1929}
Daniel Borkmann113214b2016-06-30 17:24:44 +02001930
1931struct bpf_prog *bpf_prog_get(u32 ufd)
1932{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001933 return __bpf_prog_get(ufd, NULL, false);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001934}
1935
Jakub Kicinski248f3462017-11-03 13:56:20 -07001936struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001937 bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001938{
Alexei Starovoitov4d220ed2018-04-28 19:56:37 -07001939 return __bpf_prog_get(ufd, &type, attach_drv);
Jakub Kicinski248f3462017-11-03 13:56:20 -07001940}
Jakub Kicinski6c8dfe22017-11-03 13:56:21 -07001941EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
Jakub Kicinski248f3462017-11-03 13:56:20 -07001942
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001943/* Initially all BPF programs could be loaded w/o specifying
1944 * expected_attach_type. Later for some of them specifying expected_attach_type
1945 * at load time became required so that program could be validated properly.
1946 * Programs of types that are allowed to be loaded both w/ and w/o (for
1947 * backward compatibility) expected_attach_type, should have the default attach
1948 * type assigned to expected_attach_type for the latter case, so that it can be
1949 * validated later at attach time.
1950 *
1951 * bpf_prog_load_fixup_attach_type() sets expected_attach_type in @attr if
1952 * prog type requires it but has some attach types that have to be backward
1953 * compatible.
1954 */
1955static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
1956{
1957 switch (attr->prog_type) {
1958 case BPF_PROG_TYPE_CGROUP_SOCK:
1959 /* Unfortunately BPF_ATTACH_TYPE_UNSPEC enumeration doesn't
1960 * exist so checking for non-zero is the way to go here.
1961 */
1962 if (!attr->expected_attach_type)
1963 attr->expected_attach_type =
1964 BPF_CGROUP_INET_SOCK_CREATE;
1965 break;
1966 }
1967}
1968
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001969static int
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07001970bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
1971 enum bpf_attach_type expected_attach_type,
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08001972 u32 btf_id, u32 prog_fd)
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001973{
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08001974 if (btf_id) {
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07001975 if (btf_id > BTF_MAX_TYPE)
1976 return -EINVAL;
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08001977
1978 switch (prog_type) {
1979 case BPF_PROG_TYPE_TRACING:
KP Singh9e4e01d2020-03-29 01:43:52 +01001980 case BPF_PROG_TYPE_LSM:
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08001981 case BPF_PROG_TYPE_STRUCT_OPS:
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08001982 case BPF_PROG_TYPE_EXT:
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08001983 break;
1984 default:
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07001985 return -EINVAL;
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08001986 }
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07001987 }
1988
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08001989 if (prog_fd && prog_type != BPF_PROG_TYPE_TRACING &&
1990 prog_type != BPF_PROG_TYPE_EXT)
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08001991 return -EINVAL;
1992
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07001993 switch (prog_type) {
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001994 case BPF_PROG_TYPE_CGROUP_SOCK:
1995 switch (expected_attach_type) {
1996 case BPF_CGROUP_INET_SOCK_CREATE:
1997 case BPF_CGROUP_INET4_POST_BIND:
1998 case BPF_CGROUP_INET6_POST_BIND:
1999 return 0;
2000 default:
2001 return -EINVAL;
2002 }
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002003 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2004 switch (expected_attach_type) {
2005 case BPF_CGROUP_INET4_BIND:
2006 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07002007 case BPF_CGROUP_INET4_CONNECT:
2008 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02002009 case BPF_CGROUP_INET4_GETPEERNAME:
2010 case BPF_CGROUP_INET6_GETPEERNAME:
2011 case BPF_CGROUP_INET4_GETSOCKNAME:
2012 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07002013 case BPF_CGROUP_UDP4_SENDMSG:
2014 case BPF_CGROUP_UDP6_SENDMSG:
Daniel Borkmann983695f2019-06-07 01:48:57 +02002015 case BPF_CGROUP_UDP4_RECVMSG:
2016 case BPF_CGROUP_UDP6_RECVMSG:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002017 return 0;
2018 default:
2019 return -EINVAL;
2020 }
brakmo5cf1e912019-05-28 16:59:36 -07002021 case BPF_PROG_TYPE_CGROUP_SKB:
2022 switch (expected_attach_type) {
2023 case BPF_CGROUP_INET_INGRESS:
2024 case BPF_CGROUP_INET_EGRESS:
2025 return 0;
2026 default:
2027 return -EINVAL;
2028 }
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07002029 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2030 switch (expected_attach_type) {
2031 case BPF_CGROUP_SETSOCKOPT:
2032 case BPF_CGROUP_GETSOCKOPT:
2033 return 0;
2034 default:
2035 return -EINVAL;
2036 }
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002037 case BPF_PROG_TYPE_EXT:
2038 if (expected_attach_type)
2039 return -EINVAL;
2040 /* fallthrough */
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002041 default:
2042 return 0;
2043 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002044}
2045
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002046static bool is_net_admin_prog_type(enum bpf_prog_type prog_type)
2047{
2048 switch (prog_type) {
2049 case BPF_PROG_TYPE_SCHED_CLS:
2050 case BPF_PROG_TYPE_SCHED_ACT:
2051 case BPF_PROG_TYPE_XDP:
2052 case BPF_PROG_TYPE_LWT_IN:
2053 case BPF_PROG_TYPE_LWT_OUT:
2054 case BPF_PROG_TYPE_LWT_XMIT:
2055 case BPF_PROG_TYPE_LWT_SEG6LOCAL:
2056 case BPF_PROG_TYPE_SK_SKB:
2057 case BPF_PROG_TYPE_SK_MSG:
2058 case BPF_PROG_TYPE_LIRC_MODE2:
2059 case BPF_PROG_TYPE_FLOW_DISSECTOR:
2060 case BPF_PROG_TYPE_CGROUP_DEVICE:
2061 case BPF_PROG_TYPE_CGROUP_SOCK:
2062 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2063 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2064 case BPF_PROG_TYPE_CGROUP_SYSCTL:
2065 case BPF_PROG_TYPE_SOCK_OPS:
2066 case BPF_PROG_TYPE_EXT: /* extends any prog */
2067 return true;
2068 case BPF_PROG_TYPE_CGROUP_SKB:
2069 /* always unpriv */
2070 case BPF_PROG_TYPE_SK_REUSEPORT:
2071 /* equivalent to SOCKET_FILTER. need CAP_BPF only */
2072 default:
2073 return false;
2074 }
2075}
2076
2077static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
2078{
2079 switch (prog_type) {
2080 case BPF_PROG_TYPE_KPROBE:
2081 case BPF_PROG_TYPE_TRACEPOINT:
2082 case BPF_PROG_TYPE_PERF_EVENT:
2083 case BPF_PROG_TYPE_RAW_TRACEPOINT:
2084 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
2085 case BPF_PROG_TYPE_TRACING:
2086 case BPF_PROG_TYPE_LSM:
2087 case BPF_PROG_TYPE_STRUCT_OPS: /* has access to struct sock */
2088 case BPF_PROG_TYPE_EXT: /* extends any prog */
2089 return true;
2090 default:
2091 return false;
2092 }
2093}
2094
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002095/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002096#define BPF_PROG_LOAD_LAST_FIELD attach_prog_fd
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002097
Yonghong Song838e9692018-11-19 15:29:11 -08002098static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002099{
2100 enum bpf_prog_type type = attr->prog_type;
2101 struct bpf_prog *prog;
2102 int err;
2103 char license[128];
2104 bool is_gpl;
2105
2106 if (CHECK_ATTR(BPF_PROG_LOAD))
2107 return -EINVAL;
2108
Jiong Wangc240eff2019-05-24 23:25:16 +01002109 if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
2110 BPF_F_ANY_ALIGNMENT |
Alexei Starovoitov10d274e2019-08-22 22:52:12 -07002111 BPF_F_TEST_STATE_FREQ |
Jiong Wangc240eff2019-05-24 23:25:16 +01002112 BPF_F_TEST_RND_HI32))
David S. Millere07b98d2017-05-10 11:38:07 -07002113 return -EINVAL;
2114
David Millere9ee9ef2018-11-30 21:08:14 -08002115 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
2116 (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002117 !bpf_capable())
David Millere9ee9ef2018-11-30 21:08:14 -08002118 return -EPERM;
2119
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002120 /* copy eBPF program license from user space */
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002121 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002122 sizeof(license) - 1) < 0)
2123 return -EFAULT;
2124 license[sizeof(license) - 1] = 0;
2125
2126 /* eBPF programs must be GPL compatible to use GPL-ed functions */
2127 is_gpl = license_is_gpl_compatible(license);
2128
Alexei Starovoitovc04c0d22019-04-01 21:27:45 -07002129 if (attr->insn_cnt == 0 ||
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002130 attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
Daniel Borkmannef0915c2016-12-07 01:15:44 +01002131 return -E2BIG;
Chenbo Feng80b7d812017-05-31 18:16:00 -07002132 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
2133 type != BPF_PROG_TYPE_CGROUP_SKB &&
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002134 !bpf_capable())
2135 return -EPERM;
2136
2137 if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN))
2138 return -EPERM;
2139 if (is_perfmon_prog_type(type) && !perfmon_capable())
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07002140 return -EPERM;
2141
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002142 bpf_prog_load_fixup_attach_type(attr);
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002143 if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002144 attr->attach_btf_id,
2145 attr->attach_prog_fd))
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002146 return -EINVAL;
2147
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002148 /* plain bpf_prog allocation */
2149 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
2150 if (!prog)
2151 return -ENOMEM;
2152
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002153 prog->expected_attach_type = attr->expected_attach_type;
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002154 prog->aux->attach_btf_id = attr->attach_btf_id;
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002155 if (attr->attach_prog_fd) {
2156 struct bpf_prog *tgt_prog;
2157
2158 tgt_prog = bpf_prog_get(attr->attach_prog_fd);
2159 if (IS_ERR(tgt_prog)) {
2160 err = PTR_ERR(tgt_prog);
2161 goto free_prog_nouncharge;
2162 }
2163 prog->aux->linked_prog = tgt_prog;
2164 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002165
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002166 prog->aux->offload_requested = !!attr->prog_ifindex;
2167
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002168 err = security_bpf_prog_alloc(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002169 if (err)
2170 goto free_prog_nouncharge;
2171
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002172 err = bpf_prog_charge_memlock(prog);
2173 if (err)
2174 goto free_prog_sec;
2175
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002176 prog->len = attr->insn_cnt;
2177
2178 err = -EFAULT;
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002179 if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns),
Daniel Borkmannaafe6ae2016-12-18 01:52:57 +01002180 bpf_prog_insn_size(prog)) != 0)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002181 goto free_prog;
2182
2183 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +02002184 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002185
Andrii Nakryiko85192db2019-11-17 09:28:03 -08002186 atomic64_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +02002187 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002188
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002189 if (bpf_prog_is_dev_bound(prog->aux)) {
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07002190 err = bpf_prog_offload_init(prog, attr);
2191 if (err)
2192 goto free_prog;
2193 }
2194
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002195 /* find program type: socket_filter vs tracing_filter */
2196 err = find_prog_type(type, prog);
2197 if (err < 0)
2198 goto free_prog;
2199
Jason A. Donenfeld9285ec42019-06-21 22:32:48 +02002200 prog->aux->load_time = ktime_get_boottime_ns();
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -07002201 err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
2202 sizeof(attr->prog_name));
2203 if (err < 0)
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07002204 goto free_prog;
2205
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002206 /* run eBPF verifier */
Yonghong Song838e9692018-11-19 15:29:11 -08002207 err = bpf_check(&prog, attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002208 if (err < 0)
2209 goto free_used_maps;
2210
Daniel Borkmann9facc332018-06-15 02:30:48 +02002211 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61ab2015-05-19 16:59:03 -07002212 if (err < 0)
2213 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002214
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07002215 err = bpf_prog_alloc_id(prog);
2216 if (err)
2217 goto free_used_maps;
2218
Daniel Borkmannc7517982019-08-23 22:14:23 +02002219 /* Upon success of bpf_prog_alloc_id(), the BPF prog is
2220 * effectively publicly exposed. However, retrieving via
2221 * bpf_prog_get_fd_by_id() will take another reference,
2222 * therefore it cannot be gone underneath us.
2223 *
2224 * Only for the time /after/ successful bpf_prog_new_fd()
2225 * and before returning to userspace, we might just hold
2226 * one reference and any parallel close on that fd could
2227 * rip everything out. Hence, below notifications must
2228 * happen before bpf_prog_new_fd().
2229 *
2230 * Also, any failure handling from this point onwards must
2231 * be using bpf_prog_put() given the program is exposed.
2232 */
Daniel Borkmann74451e662017-02-16 22:24:50 +01002233 bpf_prog_kallsyms_add(prog);
Song Liu6ee52e22019-01-17 08:15:15 -08002234 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
Daniel Borkmannbae141f2019-12-06 22:49:34 +01002235 bpf_audit_prog(prog, BPF_AUDIT_LOAD);
Daniel Borkmannc7517982019-08-23 22:14:23 +02002236
2237 err = bpf_prog_new_fd(prog);
2238 if (err < 0)
2239 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002240 return err;
2241
2242free_used_maps:
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02002243 /* In case we have subprogs, we need to wait for a grace
2244 * period before we can tear down JIT memory since symbols
2245 * are already exposed under kallsyms.
2246 */
2247 __bpf_prog_put_noref(prog, prog->aux->func_cnt);
2248 return err;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002249free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002250 bpf_prog_uncharge_memlock(prog);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002251free_prog_sec:
2252 security_bpf_prog_free(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002253free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002254 bpf_prog_free(prog);
2255 return err;
2256}
2257
Chenbo Feng6e71b042017-10-18 13:00:22 -07002258#define BPF_OBJ_LAST_FIELD file_flags
Daniel Borkmannb2197752015-10-29 14:58:09 +01002259
2260static int bpf_obj_pin(const union bpf_attr *attr)
2261{
Chenbo Feng6e71b042017-10-18 13:00:22 -07002262 if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
Daniel Borkmannb2197752015-10-29 14:58:09 +01002263 return -EINVAL;
2264
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002265 return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +01002266}
2267
2268static int bpf_obj_get(const union bpf_attr *attr)
2269{
Chenbo Feng6e71b042017-10-18 13:00:22 -07002270 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 ||
2271 attr->file_flags & ~BPF_OBJ_FLAG_MASK)
Daniel Borkmannb2197752015-10-29 14:58:09 +01002272 return -EINVAL;
2273
Chenbo Feng6e71b042017-10-18 13:00:22 -07002274 return bpf_obj_get_user(u64_to_user_ptr(attr->pathname),
2275 attr->file_flags);
Daniel Borkmannb2197752015-10-29 14:58:09 +01002276}
2277
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002278void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002279 const struct bpf_link_ops *ops, struct bpf_prog *prog)
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002280{
2281 atomic64_set(&link->refcnt, 1);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002282 link->type = type;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002283 link->id = 0;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002284 link->ops = ops;
2285 link->prog = prog;
2286}
2287
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002288static void bpf_link_free_id(int id)
2289{
2290 if (!id)
2291 return;
2292
2293 spin_lock_bh(&link_idr_lock);
2294 idr_remove(&link_idr, id);
2295 spin_unlock_bh(&link_idr_lock);
2296}
2297
Andrii Nakryiko98868662020-03-12 17:21:28 -07002298/* Clean up bpf_link and corresponding anon_inode file and FD. After
2299 * anon_inode is created, bpf_link can't be just kfree()'d due to deferred
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002300 * anon_inode's release() call. This helper marksbpf_link as
2301 * defunct, releases anon_inode file and puts reserved FD. bpf_prog's refcnt
2302 * is not decremented, it's the responsibility of a calling code that failed
2303 * to complete bpf_link initialization.
Andrii Nakryiko98868662020-03-12 17:21:28 -07002304 */
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002305void bpf_link_cleanup(struct bpf_link_primer *primer)
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002306{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002307 primer->link->prog = NULL;
2308 bpf_link_free_id(primer->id);
2309 fput(primer->file);
2310 put_unused_fd(primer->fd);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002311}
2312
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002313void bpf_link_inc(struct bpf_link *link)
2314{
2315 atomic64_inc(&link->refcnt);
2316}
2317
2318/* bpf_link_free is guaranteed to be called from process context */
2319static void bpf_link_free(struct bpf_link *link)
2320{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002321 bpf_link_free_id(link->id);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002322 if (link->prog) {
2323 /* detach BPF program, clean up used resources */
2324 link->ops->release(link);
2325 bpf_prog_put(link->prog);
2326 }
2327 /* free bpf_link and its containing memory */
2328 link->ops->dealloc(link);
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002329}
2330
2331static void bpf_link_put_deferred(struct work_struct *work)
2332{
2333 struct bpf_link *link = container_of(work, struct bpf_link, work);
2334
2335 bpf_link_free(link);
2336}
2337
2338/* bpf_link_put can be called from atomic context, but ensures that resources
2339 * are freed from process context
2340 */
2341void bpf_link_put(struct bpf_link *link)
2342{
2343 if (!atomic64_dec_and_test(&link->refcnt))
2344 return;
2345
2346 if (in_atomic()) {
2347 INIT_WORK(&link->work, bpf_link_put_deferred);
2348 schedule_work(&link->work);
2349 } else {
2350 bpf_link_free(link);
2351 }
2352}
2353
2354static int bpf_link_release(struct inode *inode, struct file *filp)
2355{
2356 struct bpf_link *link = filp->private_data;
2357
2358 bpf_link_put(link);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002359 return 0;
2360}
2361
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002362#ifdef CONFIG_PROC_FS
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002363#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
2364#define BPF_MAP_TYPE(_id, _ops)
2365#define BPF_LINK_TYPE(_id, _name) [_id] = #_name,
2366static const char *bpf_link_type_strs[] = {
2367 [BPF_LINK_TYPE_UNSPEC] = "<invalid>",
2368#include <linux/bpf_types.h>
2369};
2370#undef BPF_PROG_TYPE
2371#undef BPF_MAP_TYPE
2372#undef BPF_LINK_TYPE
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002373
2374static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
2375{
2376 const struct bpf_link *link = filp->private_data;
2377 const struct bpf_prog *prog = link->prog;
2378 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002379
2380 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
2381 seq_printf(m,
2382 "link_type:\t%s\n"
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002383 "link_id:\t%u\n"
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002384 "prog_tag:\t%s\n"
2385 "prog_id:\t%u\n",
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002386 bpf_link_type_strs[link->type],
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002387 link->id,
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002388 prog_tag,
2389 prog->aux->id);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002390 if (link->ops->show_fdinfo)
2391 link->ops->show_fdinfo(link, m);
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002392}
2393#endif
2394
Zou Wei6f302bf2020-04-23 10:32:40 +08002395static const struct file_operations bpf_link_fops = {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002396#ifdef CONFIG_PROC_FS
2397 .show_fdinfo = bpf_link_show_fdinfo,
2398#endif
2399 .release = bpf_link_release,
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002400 .read = bpf_dummy_read,
2401 .write = bpf_dummy_write,
2402};
2403
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002404static int bpf_link_alloc_id(struct bpf_link *link)
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002405{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002406 int id;
2407
2408 idr_preload(GFP_KERNEL);
2409 spin_lock_bh(&link_idr_lock);
2410 id = idr_alloc_cyclic(&link_idr, link, 1, INT_MAX, GFP_ATOMIC);
2411 spin_unlock_bh(&link_idr_lock);
2412 idr_preload_end();
2413
2414 return id;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002415}
2416
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002417/* Prepare bpf_link to be exposed to user-space by allocating anon_inode file,
2418 * reserving unused FD and allocating ID from link_idr. This is to be paired
2419 * with bpf_link_settle() to install FD and ID and expose bpf_link to
2420 * user-space, if bpf_link is successfully attached. If not, bpf_link and
2421 * pre-allocated resources are to be freed with bpf_cleanup() call. All the
2422 * transient state is passed around in struct bpf_link_primer.
2423 * This is preferred way to create and initialize bpf_link, especially when
2424 * there are complicated and expensive operations inbetween creating bpf_link
2425 * itself and attaching it to BPF hook. By using bpf_link_prime() and
2426 * bpf_link_settle() kernel code using bpf_link doesn't have to perform
2427 * expensive (and potentially failing) roll back operations in a rare case
2428 * that file, FD, or ID can't be allocated.
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002429 */
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002430int bpf_link_prime(struct bpf_link *link, struct bpf_link_primer *primer)
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002431{
2432 struct file *file;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002433 int fd, id;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002434
2435 fd = get_unused_fd_flags(O_CLOEXEC);
2436 if (fd < 0)
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002437 return fd;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002438
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002439
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002440 id = bpf_link_alloc_id(link);
2441 if (id < 0) {
2442 put_unused_fd(fd);
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002443 return id;
2444 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002445
2446 file = anon_inode_getfile("bpf_link", &bpf_link_fops, link, O_CLOEXEC);
2447 if (IS_ERR(file)) {
Andrii Nakryiko138c6762020-05-01 11:56:22 -07002448 bpf_link_free_id(id);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002449 put_unused_fd(fd);
Andrii Nakryiko138c6762020-05-01 11:56:22 -07002450 return PTR_ERR(file);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002451 }
2452
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002453 primer->link = link;
2454 primer->file = file;
2455 primer->fd = fd;
2456 primer->id = id;
2457 return 0;
2458}
2459
2460int bpf_link_settle(struct bpf_link_primer *primer)
2461{
2462 /* make bpf_link fetchable by ID */
2463 spin_lock_bh(&link_idr_lock);
2464 primer->link->id = primer->id;
2465 spin_unlock_bh(&link_idr_lock);
2466 /* make bpf_link fetchable by FD */
2467 fd_install(primer->fd, primer->file);
2468 /* pass through installed FD */
2469 return primer->fd;
2470}
2471
2472int bpf_link_new_fd(struct bpf_link *link)
2473{
2474 return anon_inode_getfd("bpf-link", &bpf_link_fops, link, O_CLOEXEC);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002475}
2476
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002477struct bpf_link *bpf_link_get_from_fd(u32 ufd)
2478{
2479 struct fd f = fdget(ufd);
2480 struct bpf_link *link;
2481
2482 if (!f.file)
2483 return ERR_PTR(-EBADF);
2484 if (f.file->f_op != &bpf_link_fops) {
2485 fdput(f);
2486 return ERR_PTR(-EINVAL);
2487 }
2488
2489 link = f.file->private_data;
2490 bpf_link_inc(link);
2491 fdput(f);
2492
2493 return link;
2494}
2495
2496struct bpf_tracing_link {
2497 struct bpf_link link;
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002498 enum bpf_attach_type attach_type;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002499};
2500
2501static void bpf_tracing_link_release(struct bpf_link *link)
2502{
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002503 WARN_ON_ONCE(bpf_trampoline_unlink_prog(link->prog));
2504}
2505
2506static void bpf_tracing_link_dealloc(struct bpf_link *link)
2507{
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002508 struct bpf_tracing_link *tr_link =
2509 container_of(link, struct bpf_tracing_link, link);
2510
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002511 kfree(tr_link);
2512}
2513
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002514static void bpf_tracing_link_show_fdinfo(const struct bpf_link *link,
2515 struct seq_file *seq)
2516{
2517 struct bpf_tracing_link *tr_link =
2518 container_of(link, struct bpf_tracing_link, link);
2519
2520 seq_printf(seq,
2521 "attach_type:\t%d\n",
2522 tr_link->attach_type);
2523}
2524
2525static int bpf_tracing_link_fill_link_info(const struct bpf_link *link,
2526 struct bpf_link_info *info)
2527{
2528 struct bpf_tracing_link *tr_link =
2529 container_of(link, struct bpf_tracing_link, link);
2530
2531 info->tracing.attach_type = tr_link->attach_type;
2532
2533 return 0;
2534}
2535
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002536static const struct bpf_link_ops bpf_tracing_link_lops = {
2537 .release = bpf_tracing_link_release,
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002538 .dealloc = bpf_tracing_link_dealloc,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002539 .show_fdinfo = bpf_tracing_link_show_fdinfo,
2540 .fill_link_info = bpf_tracing_link_fill_link_info,
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002541};
2542
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002543static int bpf_tracing_prog_attach(struct bpf_prog *prog)
2544{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002545 struct bpf_link_primer link_primer;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002546 struct bpf_tracing_link *link;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002547 int err;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002548
KP Singh9e4e01d2020-03-29 01:43:52 +01002549 switch (prog->type) {
2550 case BPF_PROG_TYPE_TRACING:
2551 if (prog->expected_attach_type != BPF_TRACE_FENTRY &&
2552 prog->expected_attach_type != BPF_TRACE_FEXIT &&
2553 prog->expected_attach_type != BPF_MODIFY_RETURN) {
2554 err = -EINVAL;
2555 goto out_put_prog;
2556 }
2557 break;
2558 case BPF_PROG_TYPE_EXT:
2559 if (prog->expected_attach_type != 0) {
2560 err = -EINVAL;
2561 goto out_put_prog;
2562 }
2563 break;
2564 case BPF_PROG_TYPE_LSM:
2565 if (prog->expected_attach_type != BPF_LSM_MAC) {
2566 err = -EINVAL;
2567 goto out_put_prog;
2568 }
2569 break;
2570 default:
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002571 err = -EINVAL;
2572 goto out_put_prog;
2573 }
2574
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002575 link = kzalloc(sizeof(*link), GFP_USER);
2576 if (!link) {
2577 err = -ENOMEM;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002578 goto out_put_prog;
2579 }
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002580 bpf_link_init(&link->link, BPF_LINK_TYPE_TRACING,
2581 &bpf_tracing_link_lops, prog);
2582 link->attach_type = prog->expected_attach_type;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002583
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002584 err = bpf_link_prime(&link->link, &link_primer);
2585 if (err) {
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002586 kfree(link);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002587 goto out_put_prog;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002588 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002589
2590 err = bpf_trampoline_link_prog(prog);
2591 if (err) {
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002592 bpf_link_cleanup(&link_primer);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002593 goto out_put_prog;
2594 }
2595
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002596 return bpf_link_settle(&link_primer);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002597out_put_prog:
2598 bpf_prog_put(prog);
2599 return err;
2600}
2601
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002602struct bpf_raw_tp_link {
2603 struct bpf_link link;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002604 struct bpf_raw_event_map *btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002605};
2606
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002607static void bpf_raw_tp_link_release(struct bpf_link *link)
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002608{
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002609 struct bpf_raw_tp_link *raw_tp =
2610 container_of(link, struct bpf_raw_tp_link, link);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002611
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002612 bpf_probe_unregister(raw_tp->btp, raw_tp->link.prog);
Matt Mullinsa38d1102018-12-12 16:42:37 -08002613 bpf_put_raw_tracepoint(raw_tp->btp);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002614}
2615
2616static void bpf_raw_tp_link_dealloc(struct bpf_link *link)
2617{
2618 struct bpf_raw_tp_link *raw_tp =
2619 container_of(link, struct bpf_raw_tp_link, link);
2620
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002621 kfree(raw_tp);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002622}
2623
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002624static void bpf_raw_tp_link_show_fdinfo(const struct bpf_link *link,
2625 struct seq_file *seq)
2626{
2627 struct bpf_raw_tp_link *raw_tp_link =
2628 container_of(link, struct bpf_raw_tp_link, link);
2629
2630 seq_printf(seq,
2631 "tp_name:\t%s\n",
2632 raw_tp_link->btp->tp->name);
2633}
2634
2635static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link,
2636 struct bpf_link_info *info)
2637{
2638 struct bpf_raw_tp_link *raw_tp_link =
2639 container_of(link, struct bpf_raw_tp_link, link);
2640 char __user *ubuf = u64_to_user_ptr(info->raw_tracepoint.tp_name);
2641 const char *tp_name = raw_tp_link->btp->tp->name;
2642 u32 ulen = info->raw_tracepoint.tp_name_len;
2643 size_t tp_len = strlen(tp_name);
2644
2645 if (ulen && !ubuf)
2646 return -EINVAL;
2647
2648 info->raw_tracepoint.tp_name_len = tp_len + 1;
2649
2650 if (!ubuf)
2651 return 0;
2652
2653 if (ulen >= tp_len + 1) {
2654 if (copy_to_user(ubuf, tp_name, tp_len + 1))
2655 return -EFAULT;
2656 } else {
2657 char zero = '\0';
2658
2659 if (copy_to_user(ubuf, tp_name, ulen - 1))
2660 return -EFAULT;
2661 if (put_user(zero, ubuf + ulen - 1))
2662 return -EFAULT;
2663 return -ENOSPC;
2664 }
2665
2666 return 0;
2667}
2668
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002669static const struct bpf_link_ops bpf_raw_tp_link_lops = {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002670 .release = bpf_raw_tp_link_release,
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002671 .dealloc = bpf_raw_tp_link_dealloc,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002672 .show_fdinfo = bpf_raw_tp_link_show_fdinfo,
2673 .fill_link_info = bpf_raw_tp_link_fill_link_info,
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002674};
2675
2676#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
2677
2678static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
2679{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002680 struct bpf_link_primer link_primer;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002681 struct bpf_raw_tp_link *link;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002682 struct bpf_raw_event_map *btp;
2683 struct bpf_prog *prog;
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002684 const char *tp_name;
2685 char buf[128];
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002686 int err;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002687
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002688 if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
2689 return -EINVAL;
2690
2691 prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
2692 if (IS_ERR(prog))
2693 return PTR_ERR(prog);
2694
KP Singh9e4e01d2020-03-29 01:43:52 +01002695 switch (prog->type) {
2696 case BPF_PROG_TYPE_TRACING:
2697 case BPF_PROG_TYPE_EXT:
2698 case BPF_PROG_TYPE_LSM:
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002699 if (attr->raw_tracepoint.name) {
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002700 /* The attach point for this category of programs
2701 * should be specified via btf_id during program load.
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002702 */
2703 err = -EINVAL;
2704 goto out_put_prog;
2705 }
KP Singh9e4e01d2020-03-29 01:43:52 +01002706 if (prog->type == BPF_PROG_TYPE_TRACING &&
2707 prog->expected_attach_type == BPF_TRACE_RAW_TP) {
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002708 tp_name = prog->aux->attach_func_name;
KP Singh9e4e01d2020-03-29 01:43:52 +01002709 break;
2710 }
2711 return bpf_tracing_prog_attach(prog);
2712 case BPF_PROG_TYPE_RAW_TRACEPOINT:
2713 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002714 if (strncpy_from_user(buf,
2715 u64_to_user_ptr(attr->raw_tracepoint.name),
2716 sizeof(buf) - 1) < 0) {
2717 err = -EFAULT;
2718 goto out_put_prog;
2719 }
2720 buf[sizeof(buf) - 1] = 0;
2721 tp_name = buf;
KP Singh9e4e01d2020-03-29 01:43:52 +01002722 break;
2723 default:
2724 err = -EINVAL;
2725 goto out_put_prog;
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002726 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002727
Matt Mullinsa38d1102018-12-12 16:42:37 -08002728 btp = bpf_get_raw_tracepoint(tp_name);
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002729 if (!btp) {
2730 err = -ENOENT;
2731 goto out_put_prog;
2732 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002733
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002734 link = kzalloc(sizeof(*link), GFP_USER);
2735 if (!link) {
Matt Mullinsa38d1102018-12-12 16:42:37 -08002736 err = -ENOMEM;
2737 goto out_put_btp;
2738 }
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002739 bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT,
2740 &bpf_raw_tp_link_lops, prog);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002741 link->btp = btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002742
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002743 err = bpf_link_prime(&link->link, &link_primer);
2744 if (err) {
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002745 kfree(link);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002746 goto out_put_btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002747 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002748
2749 err = bpf_probe_register(link->btp, prog);
2750 if (err) {
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002751 bpf_link_cleanup(&link_primer);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002752 goto out_put_btp;
2753 }
2754
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002755 return bpf_link_settle(&link_primer);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002756
Matt Mullinsa38d1102018-12-12 16:42:37 -08002757out_put_btp:
2758 bpf_put_raw_tracepoint(btp);
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002759out_put_prog:
2760 bpf_prog_put(prog);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002761 return err;
2762}
2763
Anders Roxell33491582018-04-03 14:09:47 +02002764static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
2765 enum bpf_attach_type attach_type)
2766{
2767 switch (prog->type) {
2768 case BPF_PROG_TYPE_CGROUP_SOCK:
2769 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07002770 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
Anders Roxell33491582018-04-03 14:09:47 +02002771 return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
brakmo5cf1e912019-05-28 16:59:36 -07002772 case BPF_PROG_TYPE_CGROUP_SKB:
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002773 if (!capable(CAP_NET_ADMIN))
2774 /* cg-skb progs can be loaded by unpriv user.
2775 * check permissions at attach time.
2776 */
2777 return -EPERM;
brakmo5cf1e912019-05-28 16:59:36 -07002778 return prog->enforce_expected_attach_type &&
2779 prog->expected_attach_type != attach_type ?
2780 -EINVAL : 0;
Anders Roxell33491582018-04-03 14:09:47 +02002781 default:
2782 return 0;
2783 }
2784}
2785
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002786static enum bpf_prog_type
2787attach_type_to_prog_type(enum bpf_attach_type attach_type)
2788{
2789 switch (attach_type) {
2790 case BPF_CGROUP_INET_INGRESS:
2791 case BPF_CGROUP_INET_EGRESS:
2792 return BPF_PROG_TYPE_CGROUP_SKB;
2793 break;
2794 case BPF_CGROUP_INET_SOCK_CREATE:
2795 case BPF_CGROUP_INET4_POST_BIND:
2796 case BPF_CGROUP_INET6_POST_BIND:
2797 return BPF_PROG_TYPE_CGROUP_SOCK;
2798 case BPF_CGROUP_INET4_BIND:
2799 case BPF_CGROUP_INET6_BIND:
2800 case BPF_CGROUP_INET4_CONNECT:
2801 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02002802 case BPF_CGROUP_INET4_GETPEERNAME:
2803 case BPF_CGROUP_INET6_GETPEERNAME:
2804 case BPF_CGROUP_INET4_GETSOCKNAME:
2805 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002806 case BPF_CGROUP_UDP4_SENDMSG:
2807 case BPF_CGROUP_UDP6_SENDMSG:
2808 case BPF_CGROUP_UDP4_RECVMSG:
2809 case BPF_CGROUP_UDP6_RECVMSG:
2810 return BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
2811 case BPF_CGROUP_SOCK_OPS:
2812 return BPF_PROG_TYPE_SOCK_OPS;
2813 case BPF_CGROUP_DEVICE:
2814 return BPF_PROG_TYPE_CGROUP_DEVICE;
2815 case BPF_SK_MSG_VERDICT:
2816 return BPF_PROG_TYPE_SK_MSG;
2817 case BPF_SK_SKB_STREAM_PARSER:
2818 case BPF_SK_SKB_STREAM_VERDICT:
2819 return BPF_PROG_TYPE_SK_SKB;
2820 case BPF_LIRC_MODE2:
2821 return BPF_PROG_TYPE_LIRC_MODE2;
2822 case BPF_FLOW_DISSECTOR:
2823 return BPF_PROG_TYPE_FLOW_DISSECTOR;
2824 case BPF_CGROUP_SYSCTL:
2825 return BPF_PROG_TYPE_CGROUP_SYSCTL;
2826 case BPF_CGROUP_GETSOCKOPT:
2827 case BPF_CGROUP_SETSOCKOPT:
2828 return BPF_PROG_TYPE_CGROUP_SOCKOPT;
Yonghong Songde4e05c2020-05-09 10:59:01 -07002829 case BPF_TRACE_ITER:
2830 return BPF_PROG_TYPE_TRACING;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002831 default:
2832 return BPF_PROG_TYPE_UNSPEC;
2833 }
2834}
2835
Andrey Ignatov7dd68b32019-12-18 23:44:35 -08002836#define BPF_PROG_ATTACH_LAST_FIELD replace_bpf_fd
John Fastabend174a79f2017-08-15 22:32:47 -07002837
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07002838#define BPF_F_ATTACH_MASK \
Andrey Ignatov7dd68b32019-12-18 23:44:35 -08002839 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI | BPF_F_REPLACE)
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07002840
Daniel Mackf4324552016-11-23 16:52:27 +01002841static int bpf_prog_attach(const union bpf_attr *attr)
2842{
Alexei Starovoitov7f677632017-02-10 20:28:24 -08002843 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01002844 struct bpf_prog *prog;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08002845 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01002846
Daniel Mackf4324552016-11-23 16:52:27 +01002847 if (CHECK_ATTR(BPF_PROG_ATTACH))
2848 return -EINVAL;
2849
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07002850 if (attr->attach_flags & ~BPF_F_ATTACH_MASK)
Alexei Starovoitov7f677632017-02-10 20:28:24 -08002851 return -EINVAL;
2852
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002853 ptype = attach_type_to_prog_type(attr->attach_type);
2854 if (ptype == BPF_PROG_TYPE_UNSPEC)
Daniel Mackf4324552016-11-23 16:52:27 +01002855 return -EINVAL;
Daniel Mackf4324552016-11-23 16:52:27 +01002856
David Ahernb2cd1252016-12-01 08:48:03 -08002857 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
2858 if (IS_ERR(prog))
2859 return PTR_ERR(prog);
2860
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002861 if (bpf_prog_attach_check_attach_type(prog, attr->attach_type)) {
2862 bpf_prog_put(prog);
2863 return -EINVAL;
2864 }
2865
Sean Youngfdb5c452018-06-19 00:04:24 +01002866 switch (ptype) {
2867 case BPF_PROG_TYPE_SK_SKB:
2868 case BPF_PROG_TYPE_SK_MSG:
Daniel Borkmann604326b2018-10-13 02:45:58 +02002869 ret = sock_map_get_from_fd(attr, prog);
Sean Youngfdb5c452018-06-19 00:04:24 +01002870 break;
2871 case BPF_PROG_TYPE_LIRC_MODE2:
2872 ret = lirc_prog_attach(attr, prog);
2873 break;
Petar Penkovd58e4682018-09-14 07:46:18 -07002874 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02002875 ret = netns_bpf_prog_attach(attr, prog);
Petar Penkovd58e4682018-09-14 07:46:18 -07002876 break;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002877 case BPF_PROG_TYPE_CGROUP_DEVICE:
2878 case BPF_PROG_TYPE_CGROUP_SKB:
2879 case BPF_PROG_TYPE_CGROUP_SOCK:
2880 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2881 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2882 case BPF_PROG_TYPE_CGROUP_SYSCTL:
2883 case BPF_PROG_TYPE_SOCK_OPS:
Sean Youngfdb5c452018-06-19 00:04:24 +01002884 ret = cgroup_bpf_prog_attach(attr, ptype, prog);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002885 break;
2886 default:
2887 ret = -EINVAL;
David Ahernb2cd1252016-12-01 08:48:03 -08002888 }
2889
Alexei Starovoitov7f677632017-02-10 20:28:24 -08002890 if (ret)
2891 bpf_prog_put(prog);
Alexei Starovoitov7f677632017-02-10 20:28:24 -08002892 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01002893}
2894
2895#define BPF_PROG_DETACH_LAST_FIELD attach_type
2896
2897static int bpf_prog_detach(const union bpf_attr *attr)
2898{
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07002899 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01002900
Daniel Mackf4324552016-11-23 16:52:27 +01002901 if (CHECK_ATTR(BPF_PROG_DETACH))
2902 return -EINVAL;
2903
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002904 ptype = attach_type_to_prog_type(attr->attach_type);
2905
2906 switch (ptype) {
2907 case BPF_PROG_TYPE_SK_MSG:
2908 case BPF_PROG_TYPE_SK_SKB:
Daniel Borkmann604326b2018-10-13 02:45:58 +02002909 return sock_map_get_from_fd(attr, NULL);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002910 case BPF_PROG_TYPE_LIRC_MODE2:
Sean Youngf4364dc2018-05-27 12:24:09 +01002911 return lirc_prog_detach(attr);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002912 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002913 if (!capable(CAP_NET_ADMIN))
2914 return -EPERM;
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02002915 return netns_bpf_prog_detach(attr);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002916 case BPF_PROG_TYPE_CGROUP_DEVICE:
2917 case BPF_PROG_TYPE_CGROUP_SKB:
2918 case BPF_PROG_TYPE_CGROUP_SOCK:
2919 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2920 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2921 case BPF_PROG_TYPE_CGROUP_SYSCTL:
2922 case BPF_PROG_TYPE_SOCK_OPS:
2923 return cgroup_bpf_prog_detach(attr, ptype);
Daniel Mackf4324552016-11-23 16:52:27 +01002924 default:
2925 return -EINVAL;
2926 }
Daniel Mackf4324552016-11-23 16:52:27 +01002927}
Lawrence Brakmo40304b22017-06-30 20:02:40 -07002928
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07002929#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
2930
2931static int bpf_prog_query(const union bpf_attr *attr,
2932 union bpf_attr __user *uattr)
2933{
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07002934 if (!capable(CAP_NET_ADMIN))
2935 return -EPERM;
2936 if (CHECK_ATTR(BPF_PROG_QUERY))
2937 return -EINVAL;
2938 if (attr->query.query_flags & ~BPF_F_QUERY_EFFECTIVE)
2939 return -EINVAL;
2940
2941 switch (attr->query.attach_type) {
2942 case BPF_CGROUP_INET_INGRESS:
2943 case BPF_CGROUP_INET_EGRESS:
2944 case BPF_CGROUP_INET_SOCK_CREATE:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002945 case BPF_CGROUP_INET4_BIND:
2946 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002947 case BPF_CGROUP_INET4_POST_BIND:
2948 case BPF_CGROUP_INET6_POST_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07002949 case BPF_CGROUP_INET4_CONNECT:
2950 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02002951 case BPF_CGROUP_INET4_GETPEERNAME:
2952 case BPF_CGROUP_INET6_GETPEERNAME:
2953 case BPF_CGROUP_INET4_GETSOCKNAME:
2954 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07002955 case BPF_CGROUP_UDP4_SENDMSG:
2956 case BPF_CGROUP_UDP6_SENDMSG:
Daniel Borkmann983695f2019-06-07 01:48:57 +02002957 case BPF_CGROUP_UDP4_RECVMSG:
2958 case BPF_CGROUP_UDP6_RECVMSG:
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07002959 case BPF_CGROUP_SOCK_OPS:
Roman Gushchinebc614f2017-11-05 08:15:32 -05002960 case BPF_CGROUP_DEVICE:
Andrey Ignatov7b146ce2019-02-27 12:59:24 -08002961 case BPF_CGROUP_SYSCTL:
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07002962 case BPF_CGROUP_GETSOCKOPT:
2963 case BPF_CGROUP_SETSOCKOPT:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002964 return cgroup_bpf_prog_query(attr, uattr);
Sean Youngf4364dc2018-05-27 12:24:09 +01002965 case BPF_LIRC_MODE2:
2966 return lirc_prog_query(attr, uattr);
Stanislav Fomichev118c8e92019-04-25 14:37:23 -07002967 case BPF_FLOW_DISSECTOR:
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02002968 return netns_bpf_prog_query(attr, uattr);
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07002969 default:
2970 return -EINVAL;
2971 }
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07002972}
Daniel Mackf4324552016-11-23 16:52:27 +01002973
Stanislav Fomichevb0b93952019-04-09 11:49:09 -07002974#define BPF_PROG_TEST_RUN_LAST_FIELD test.ctx_out
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07002975
2976static int bpf_prog_test_run(const union bpf_attr *attr,
2977 union bpf_attr __user *uattr)
2978{
2979 struct bpf_prog *prog;
2980 int ret = -ENOTSUPP;
2981
2982 if (CHECK_ATTR(BPF_PROG_TEST_RUN))
2983 return -EINVAL;
2984
Stanislav Fomichevb0b93952019-04-09 11:49:09 -07002985 if ((attr->test.ctx_size_in && !attr->test.ctx_in) ||
2986 (!attr->test.ctx_size_in && attr->test.ctx_in))
2987 return -EINVAL;
2988
2989 if ((attr->test.ctx_size_out && !attr->test.ctx_out) ||
2990 (!attr->test.ctx_size_out && attr->test.ctx_out))
2991 return -EINVAL;
2992
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07002993 prog = bpf_prog_get(attr->test.prog_fd);
2994 if (IS_ERR(prog))
2995 return PTR_ERR(prog);
2996
2997 if (prog->aux->ops->test_run)
2998 ret = prog->aux->ops->test_run(prog, attr, uattr);
2999
3000 bpf_prog_put(prog);
3001 return ret;
3002}
3003
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07003004#define BPF_OBJ_GET_NEXT_ID_LAST_FIELD next_id
3005
3006static int bpf_obj_get_next_id(const union bpf_attr *attr,
3007 union bpf_attr __user *uattr,
3008 struct idr *idr,
3009 spinlock_t *lock)
3010{
3011 u32 next_id = attr->start_id;
3012 int err = 0;
3013
3014 if (CHECK_ATTR(BPF_OBJ_GET_NEXT_ID) || next_id >= INT_MAX)
3015 return -EINVAL;
3016
3017 if (!capable(CAP_SYS_ADMIN))
3018 return -EPERM;
3019
3020 next_id++;
3021 spin_lock_bh(lock);
3022 if (!idr_get_next(idr, &next_id))
3023 err = -ENOENT;
3024 spin_unlock_bh(lock);
3025
3026 if (!err)
3027 err = put_user(next_id, &uattr->next_id);
3028
3029 return err;
3030}
3031
Yonghong Song6086d292020-05-09 10:59:09 -07003032struct bpf_map *bpf_map_get_curr_or_next(u32 *id)
3033{
3034 struct bpf_map *map;
3035
3036 spin_lock_bh(&map_idr_lock);
3037again:
3038 map = idr_get_next(&map_idr, id);
3039 if (map) {
3040 map = __bpf_map_inc_not_zero(map, false);
3041 if (IS_ERR(map)) {
3042 (*id)++;
3043 goto again;
3044 }
3045 }
3046 spin_unlock_bh(&map_idr_lock);
3047
3048 return map;
3049}
3050
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003051#define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
3052
Björn Töpel7e6897f2019-12-13 18:51:09 +01003053struct bpf_prog *bpf_prog_by_id(u32 id)
3054{
3055 struct bpf_prog *prog;
3056
3057 if (!id)
3058 return ERR_PTR(-ENOENT);
3059
3060 spin_lock_bh(&prog_idr_lock);
3061 prog = idr_find(&prog_idr, id);
3062 if (prog)
3063 prog = bpf_prog_inc_not_zero(prog);
3064 else
3065 prog = ERR_PTR(-ENOENT);
3066 spin_unlock_bh(&prog_idr_lock);
3067 return prog;
3068}
3069
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003070static int bpf_prog_get_fd_by_id(const union bpf_attr *attr)
3071{
3072 struct bpf_prog *prog;
3073 u32 id = attr->prog_id;
3074 int fd;
3075
3076 if (CHECK_ATTR(BPF_PROG_GET_FD_BY_ID))
3077 return -EINVAL;
3078
3079 if (!capable(CAP_SYS_ADMIN))
3080 return -EPERM;
3081
Björn Töpel7e6897f2019-12-13 18:51:09 +01003082 prog = bpf_prog_by_id(id);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003083 if (IS_ERR(prog))
3084 return PTR_ERR(prog);
3085
3086 fd = bpf_prog_new_fd(prog);
3087 if (fd < 0)
3088 bpf_prog_put(prog);
3089
3090 return fd;
3091}
3092
Chenbo Feng6e71b042017-10-18 13:00:22 -07003093#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD open_flags
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003094
3095static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
3096{
3097 struct bpf_map *map;
3098 u32 id = attr->map_id;
Chenbo Feng6e71b042017-10-18 13:00:22 -07003099 int f_flags;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003100 int fd;
3101
Chenbo Feng6e71b042017-10-18 13:00:22 -07003102 if (CHECK_ATTR(BPF_MAP_GET_FD_BY_ID) ||
3103 attr->open_flags & ~BPF_OBJ_FLAG_MASK)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003104 return -EINVAL;
3105
3106 if (!capable(CAP_SYS_ADMIN))
3107 return -EPERM;
3108
Chenbo Feng6e71b042017-10-18 13:00:22 -07003109 f_flags = bpf_get_file_flag(attr->open_flags);
3110 if (f_flags < 0)
3111 return f_flags;
3112
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003113 spin_lock_bh(&map_idr_lock);
3114 map = idr_find(&map_idr, id);
3115 if (map)
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07003116 map = __bpf_map_inc_not_zero(map, true);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003117 else
3118 map = ERR_PTR(-ENOENT);
3119 spin_unlock_bh(&map_idr_lock);
3120
3121 if (IS_ERR(map))
3122 return PTR_ERR(map);
3123
Chenbo Feng6e71b042017-10-18 13:00:22 -07003124 fd = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003125 if (fd < 0)
Peng Sun781e6282019-02-26 22:15:37 +08003126 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003127
3128 return fd;
3129}
3130
Daniel Borkmann7105e822017-12-20 13:42:57 +01003131static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003132 unsigned long addr, u32 *off,
3133 u32 *type)
Daniel Borkmann7105e822017-12-20 13:42:57 +01003134{
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003135 const struct bpf_map *map;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003136 int i;
3137
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003138 for (i = 0, *off = 0; i < prog->aux->used_map_cnt; i++) {
3139 map = prog->aux->used_maps[i];
3140 if (map == (void *)addr) {
3141 *type = BPF_PSEUDO_MAP_FD;
3142 return map;
3143 }
3144 if (!map->ops->map_direct_value_meta)
3145 continue;
3146 if (!map->ops->map_direct_value_meta(map, addr, off)) {
3147 *type = BPF_PSEUDO_MAP_VALUE;
3148 return map;
3149 }
3150 }
3151
Daniel Borkmann7105e822017-12-20 13:42:57 +01003152 return NULL;
3153}
3154
3155static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
3156{
3157 const struct bpf_map *map;
3158 struct bpf_insn *insns;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003159 u32 off, type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003160 u64 imm;
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003161 u8 code;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003162 int i;
3163
3164 insns = kmemdup(prog->insnsi, bpf_prog_insn_size(prog),
3165 GFP_USER);
3166 if (!insns)
3167 return insns;
3168
3169 for (i = 0; i < prog->len; i++) {
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003170 code = insns[i].code;
3171
3172 if (code == (BPF_JMP | BPF_TAIL_CALL)) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003173 insns[i].code = BPF_JMP | BPF_CALL;
3174 insns[i].imm = BPF_FUNC_tail_call;
3175 /* fall-through */
3176 }
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003177 if (code == (BPF_JMP | BPF_CALL) ||
3178 code == (BPF_JMP | BPF_CALL_ARGS)) {
3179 if (code == (BPF_JMP | BPF_CALL_ARGS))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003180 insns[i].code = BPF_JMP | BPF_CALL;
3181 if (!bpf_dump_raw_ok())
3182 insns[i].imm = 0;
3183 continue;
3184 }
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003185 if (BPF_CLASS(code) == BPF_LDX && BPF_MODE(code) == BPF_PROBE_MEM) {
3186 insns[i].code = BPF_LDX | BPF_SIZE(code) | BPF_MEM;
3187 continue;
3188 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01003189
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003190 if (code != (BPF_LD | BPF_IMM | BPF_DW))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003191 continue;
3192
3193 imm = ((u64)insns[i + 1].imm << 32) | (u32)insns[i].imm;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003194 map = bpf_map_from_imm(prog, imm, &off, &type);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003195 if (map) {
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003196 insns[i].src_reg = type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003197 insns[i].imm = map->id;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003198 insns[i + 1].imm = off;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003199 continue;
3200 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01003201 }
3202
3203 return insns;
3204}
3205
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003206static int set_info_rec_size(struct bpf_prog_info *info)
3207{
3208 /*
3209 * Ensure info.*_rec_size is the same as kernel expected size
3210 *
3211 * or
3212 *
3213 * Only allow zero *_rec_size if both _rec_size and _cnt are
3214 * zero. In this case, the kernel will set the expected
3215 * _rec_size back to the info.
3216 */
3217
Yonghong Song11d8b822018-12-10 14:14:08 -08003218 if ((info->nr_func_info || info->func_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003219 info->func_info_rec_size != sizeof(struct bpf_func_info))
3220 return -EINVAL;
3221
Yonghong Song11d8b822018-12-10 14:14:08 -08003222 if ((info->nr_line_info || info->line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003223 info->line_info_rec_size != sizeof(struct bpf_line_info))
3224 return -EINVAL;
3225
Yonghong Song11d8b822018-12-10 14:14:08 -08003226 if ((info->nr_jited_line_info || info->jited_line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003227 info->jited_line_info_rec_size != sizeof(__u64))
3228 return -EINVAL;
3229
3230 info->func_info_rec_size = sizeof(struct bpf_func_info);
3231 info->line_info_rec_size = sizeof(struct bpf_line_info);
3232 info->jited_line_info_rec_size = sizeof(__u64);
3233
3234 return 0;
3235}
3236
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003237static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
3238 const union bpf_attr *attr,
3239 union bpf_attr __user *uattr)
3240{
3241 struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003242 struct bpf_prog_info info;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003243 u32 info_len = attr->info.info_len;
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08003244 struct bpf_prog_stats stats;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003245 char __user *uinsns;
3246 u32 ulen;
3247 int err;
3248
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07003249 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003250 if (err)
3251 return err;
3252 info_len = min_t(u32, sizeof(info), info_len);
3253
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003254 memset(&info, 0, sizeof(info));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003255 if (copy_from_user(&info, uinfo, info_len))
Daniel Borkmann89b09682017-07-27 21:02:46 +02003256 return -EFAULT;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003257
3258 info.type = prog->type;
3259 info.id = prog->aux->id;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003260 info.load_time = prog->aux->load_time;
3261 info.created_by_uid = from_kuid_munged(current_user_ns(),
3262 prog->aux->user->uid);
Jiri Olsab85fab02018-04-25 19:41:06 +02003263 info.gpl_compatible = prog->gpl_compatible;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003264
3265 memcpy(info.tag, prog->tag, sizeof(prog->tag));
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003266 memcpy(info.name, prog->aux->name, sizeof(prog->aux->name));
3267
3268 ulen = info.nr_map_ids;
3269 info.nr_map_ids = prog->aux->used_map_cnt;
3270 ulen = min_t(u32, info.nr_map_ids, ulen);
3271 if (ulen) {
Martin KaFai Lau721e08d2017-09-29 10:52:17 -07003272 u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003273 u32 i;
3274
3275 for (i = 0; i < ulen; i++)
3276 if (put_user(prog->aux->used_maps[i]->id,
3277 &user_map_ids[i]))
3278 return -EFAULT;
3279 }
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003280
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003281 err = set_info_rec_size(&info);
3282 if (err)
3283 return err;
Martin KaFai Lau73372242018-12-05 17:35:43 -08003284
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08003285 bpf_prog_get_stats(prog, &stats);
3286 info.run_time_ns = stats.nsecs;
3287 info.run_cnt = stats.cnt;
3288
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07003289 if (!bpf_capable()) {
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003290 info.jited_prog_len = 0;
3291 info.xlated_prog_len = 0;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303292 info.nr_jited_ksyms = 0;
Daniel Borkmann28c2fae2018-11-02 11:35:46 +01003293 info.nr_jited_func_lens = 0;
Yonghong Song11d8b822018-12-10 14:14:08 -08003294 info.nr_func_info = 0;
3295 info.nr_line_info = 0;
3296 info.nr_jited_line_info = 0;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003297 goto done;
3298 }
3299
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003300 ulen = info.xlated_prog_len;
Daniel Borkmann9975a542017-07-28 17:05:25 +02003301 info.xlated_prog_len = bpf_prog_insn_size(prog);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003302 if (info.xlated_prog_len && ulen) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003303 struct bpf_insn *insns_sanitized;
3304 bool fault;
3305
3306 if (prog->blinded && !bpf_dump_raw_ok()) {
3307 info.xlated_prog_insns = 0;
3308 goto done;
3309 }
3310 insns_sanitized = bpf_insn_prepare_dump(prog);
3311 if (!insns_sanitized)
3312 return -ENOMEM;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003313 uinsns = u64_to_user_ptr(info.xlated_prog_insns);
3314 ulen = min_t(u32, info.xlated_prog_len, ulen);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003315 fault = copy_to_user(uinsns, insns_sanitized, ulen);
3316 kfree(insns_sanitized);
3317 if (fault)
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003318 return -EFAULT;
3319 }
3320
Jakub Kicinski675fc272017-12-27 18:39:09 -08003321 if (bpf_prog_is_dev_bound(prog->aux)) {
3322 err = bpf_prog_offload_info_fill(&info, prog);
3323 if (err)
3324 return err;
Jiong Wangfcfb1262018-01-16 16:05:19 -08003325 goto done;
3326 }
3327
3328 /* NOTE: the following code is supposed to be skipped for offload.
3329 * bpf_prog_offload_info_fill() is the place to fill similar fields
3330 * for offload.
3331 */
3332 ulen = info.jited_prog_len;
Sandipan Das4d56a762018-05-24 12:26:51 +05303333 if (prog->aux->func_cnt) {
3334 u32 i;
3335
3336 info.jited_prog_len = 0;
3337 for (i = 0; i < prog->aux->func_cnt; i++)
3338 info.jited_prog_len += prog->aux->func[i]->jited_len;
3339 } else {
3340 info.jited_prog_len = prog->jited_len;
3341 }
3342
Jiong Wangfcfb1262018-01-16 16:05:19 -08003343 if (info.jited_prog_len && ulen) {
3344 if (bpf_dump_raw_ok()) {
3345 uinsns = u64_to_user_ptr(info.jited_prog_insns);
3346 ulen = min_t(u32, info.jited_prog_len, ulen);
Sandipan Das4d56a762018-05-24 12:26:51 +05303347
3348 /* for multi-function programs, copy the JITed
3349 * instructions for all the functions
3350 */
3351 if (prog->aux->func_cnt) {
3352 u32 len, free, i;
3353 u8 *img;
3354
3355 free = ulen;
3356 for (i = 0; i < prog->aux->func_cnt; i++) {
3357 len = prog->aux->func[i]->jited_len;
3358 len = min_t(u32, len, free);
3359 img = (u8 *) prog->aux->func[i]->bpf_func;
3360 if (copy_to_user(uinsns, img, len))
3361 return -EFAULT;
3362 uinsns += len;
3363 free -= len;
3364 if (!free)
3365 break;
3366 }
3367 } else {
3368 if (copy_to_user(uinsns, prog->bpf_func, ulen))
3369 return -EFAULT;
3370 }
Jiong Wangfcfb1262018-01-16 16:05:19 -08003371 } else {
3372 info.jited_prog_insns = 0;
3373 }
Jakub Kicinski675fc272017-12-27 18:39:09 -08003374 }
3375
Sandipan Dasdbecd732018-05-24 12:26:48 +05303376 ulen = info.nr_jited_ksyms;
Song Liuff1889f2018-11-02 10:16:17 -07003377 info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08003378 if (ulen) {
Sandipan Dasdbecd732018-05-24 12:26:48 +05303379 if (bpf_dump_raw_ok()) {
Song Liuff1889f2018-11-02 10:16:17 -07003380 unsigned long ksym_addr;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303381 u64 __user *user_ksyms;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303382 u32 i;
3383
3384 /* copy the address of the kernel symbol
3385 * corresponding to each function
3386 */
3387 ulen = min_t(u32, info.nr_jited_ksyms, ulen);
3388 user_ksyms = u64_to_user_ptr(info.jited_ksyms);
Song Liuff1889f2018-11-02 10:16:17 -07003389 if (prog->aux->func_cnt) {
3390 for (i = 0; i < ulen; i++) {
3391 ksym_addr = (unsigned long)
3392 prog->aux->func[i]->bpf_func;
3393 if (put_user((u64) ksym_addr,
3394 &user_ksyms[i]))
3395 return -EFAULT;
3396 }
3397 } else {
3398 ksym_addr = (unsigned long) prog->bpf_func;
3399 if (put_user((u64) ksym_addr, &user_ksyms[0]))
Sandipan Dasdbecd732018-05-24 12:26:48 +05303400 return -EFAULT;
3401 }
3402 } else {
3403 info.jited_ksyms = 0;
3404 }
3405 }
3406
Sandipan Das815581c2018-05-24 12:26:52 +05303407 ulen = info.nr_jited_func_lens;
Song Liuff1889f2018-11-02 10:16:17 -07003408 info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08003409 if (ulen) {
Sandipan Das815581c2018-05-24 12:26:52 +05303410 if (bpf_dump_raw_ok()) {
3411 u32 __user *user_lens;
3412 u32 func_len, i;
3413
3414 /* copy the JITed image lengths for each function */
3415 ulen = min_t(u32, info.nr_jited_func_lens, ulen);
3416 user_lens = u64_to_user_ptr(info.jited_func_lens);
Song Liuff1889f2018-11-02 10:16:17 -07003417 if (prog->aux->func_cnt) {
3418 for (i = 0; i < ulen; i++) {
3419 func_len =
3420 prog->aux->func[i]->jited_len;
3421 if (put_user(func_len, &user_lens[i]))
3422 return -EFAULT;
3423 }
3424 } else {
3425 func_len = prog->jited_len;
3426 if (put_user(func_len, &user_lens[0]))
Sandipan Das815581c2018-05-24 12:26:52 +05303427 return -EFAULT;
3428 }
3429 } else {
3430 info.jited_func_lens = 0;
3431 }
3432 }
3433
Martin KaFai Lau73372242018-12-05 17:35:43 -08003434 if (prog->aux->btf)
Yonghong Song838e9692018-11-19 15:29:11 -08003435 info.btf_id = btf_id(prog->aux->btf);
3436
Yonghong Song11d8b822018-12-10 14:14:08 -08003437 ulen = info.nr_func_info;
3438 info.nr_func_info = prog->aux->func_info_cnt;
3439 if (info.nr_func_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003440 char __user *user_finfo;
Yonghong Song838e9692018-11-19 15:29:11 -08003441
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003442 user_finfo = u64_to_user_ptr(info.func_info);
3443 ulen = min_t(u32, info.nr_func_info, ulen);
3444 if (copy_to_user(user_finfo, prog->aux->func_info,
3445 info.func_info_rec_size * ulen))
3446 return -EFAULT;
Yonghong Song838e9692018-11-19 15:29:11 -08003447 }
3448
Yonghong Song11d8b822018-12-10 14:14:08 -08003449 ulen = info.nr_line_info;
3450 info.nr_line_info = prog->aux->nr_linfo;
3451 if (info.nr_line_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003452 __u8 __user *user_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003453
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003454 user_linfo = u64_to_user_ptr(info.line_info);
3455 ulen = min_t(u32, info.nr_line_info, ulen);
3456 if (copy_to_user(user_linfo, prog->aux->linfo,
3457 info.line_info_rec_size * ulen))
3458 return -EFAULT;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003459 }
3460
Yonghong Song11d8b822018-12-10 14:14:08 -08003461 ulen = info.nr_jited_line_info;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003462 if (prog->aux->jited_linfo)
Yonghong Song11d8b822018-12-10 14:14:08 -08003463 info.nr_jited_line_info = prog->aux->nr_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003464 else
Yonghong Song11d8b822018-12-10 14:14:08 -08003465 info.nr_jited_line_info = 0;
3466 if (info.nr_jited_line_info && ulen) {
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003467 if (bpf_dump_raw_ok()) {
3468 __u64 __user *user_linfo;
3469 u32 i;
3470
3471 user_linfo = u64_to_user_ptr(info.jited_line_info);
Yonghong Song11d8b822018-12-10 14:14:08 -08003472 ulen = min_t(u32, info.nr_jited_line_info, ulen);
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003473 for (i = 0; i < ulen; i++) {
3474 if (put_user((__u64)(long)prog->aux->jited_linfo[i],
3475 &user_linfo[i]))
3476 return -EFAULT;
3477 }
3478 } else {
3479 info.jited_line_info = 0;
3480 }
3481 }
3482
Song Liuc872bdb2018-12-12 09:37:46 -08003483 ulen = info.nr_prog_tags;
3484 info.nr_prog_tags = prog->aux->func_cnt ? : 1;
3485 if (ulen) {
3486 __u8 __user (*user_prog_tags)[BPF_TAG_SIZE];
3487 u32 i;
3488
3489 user_prog_tags = u64_to_user_ptr(info.prog_tags);
3490 ulen = min_t(u32, info.nr_prog_tags, ulen);
3491 if (prog->aux->func_cnt) {
3492 for (i = 0; i < ulen; i++) {
3493 if (copy_to_user(user_prog_tags[i],
3494 prog->aux->func[i]->tag,
3495 BPF_TAG_SIZE))
3496 return -EFAULT;
3497 }
3498 } else {
3499 if (copy_to_user(user_prog_tags[0],
3500 prog->tag, BPF_TAG_SIZE))
3501 return -EFAULT;
3502 }
3503 }
3504
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003505done:
3506 if (copy_to_user(uinfo, &info, info_len) ||
3507 put_user(info_len, &uattr->info.info_len))
3508 return -EFAULT;
3509
3510 return 0;
3511}
3512
3513static int bpf_map_get_info_by_fd(struct bpf_map *map,
3514 const union bpf_attr *attr,
3515 union bpf_attr __user *uattr)
3516{
3517 struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003518 struct bpf_map_info info;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003519 u32 info_len = attr->info.info_len;
3520 int err;
3521
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07003522 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003523 if (err)
3524 return err;
3525 info_len = min_t(u32, sizeof(info), info_len);
3526
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003527 memset(&info, 0, sizeof(info));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003528 info.type = map->map_type;
3529 info.id = map->id;
3530 info.key_size = map->key_size;
3531 info.value_size = map->value_size;
3532 info.max_entries = map->max_entries;
3533 info.map_flags = map->map_flags;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -07003534 memcpy(info.name, map->name, sizeof(map->name));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003535
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003536 if (map->btf) {
3537 info.btf_id = btf_id(map->btf);
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -07003538 info.btf_key_type_id = map->btf_key_type_id;
3539 info.btf_value_type_id = map->btf_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003540 }
Martin KaFai Lau85d33df2020-01-08 16:35:05 -08003541 info.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003542
Jakub Kicinski52775b32018-01-17 19:13:28 -08003543 if (bpf_map_is_dev_bound(map)) {
3544 err = bpf_map_offload_info_fill(&info, map);
3545 if (err)
3546 return err;
3547 }
3548
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003549 if (copy_to_user(uinfo, &info, info_len) ||
3550 put_user(info_len, &uattr->info.info_len))
3551 return -EFAULT;
3552
3553 return 0;
3554}
3555
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003556static int bpf_btf_get_info_by_fd(struct btf *btf,
3557 const union bpf_attr *attr,
3558 union bpf_attr __user *uattr)
3559{
3560 struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info);
3561 u32 info_len = attr->info.info_len;
3562 int err;
3563
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07003564 err = bpf_check_uarg_tail_zero(uinfo, sizeof(*uinfo), info_len);
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003565 if (err)
3566 return err;
3567
3568 return btf_get_info_by_fd(btf, attr, uattr);
3569}
3570
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003571static int bpf_link_get_info_by_fd(struct bpf_link *link,
3572 const union bpf_attr *attr,
3573 union bpf_attr __user *uattr)
3574{
3575 struct bpf_link_info __user *uinfo = u64_to_user_ptr(attr->info.info);
3576 struct bpf_link_info info;
3577 u32 info_len = attr->info.info_len;
3578 int err;
3579
3580 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
3581 if (err)
3582 return err;
3583 info_len = min_t(u32, sizeof(info), info_len);
3584
3585 memset(&info, 0, sizeof(info));
3586 if (copy_from_user(&info, uinfo, info_len))
3587 return -EFAULT;
3588
3589 info.type = link->type;
3590 info.id = link->id;
3591 info.prog_id = link->prog->aux->id;
3592
3593 if (link->ops->fill_link_info) {
3594 err = link->ops->fill_link_info(link, &info);
3595 if (err)
3596 return err;
3597 }
3598
3599 if (copy_to_user(uinfo, &info, info_len) ||
3600 put_user(info_len, &uattr->info.info_len))
3601 return -EFAULT;
3602
3603 return 0;
3604}
3605
3606
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003607#define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info
3608
3609static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
3610 union bpf_attr __user *uattr)
3611{
3612 int ufd = attr->info.bpf_fd;
3613 struct fd f;
3614 int err;
3615
3616 if (CHECK_ATTR(BPF_OBJ_GET_INFO_BY_FD))
3617 return -EINVAL;
3618
3619 f = fdget(ufd);
3620 if (!f.file)
3621 return -EBADFD;
3622
3623 if (f.file->f_op == &bpf_prog_fops)
3624 err = bpf_prog_get_info_by_fd(f.file->private_data, attr,
3625 uattr);
3626 else if (f.file->f_op == &bpf_map_fops)
3627 err = bpf_map_get_info_by_fd(f.file->private_data, attr,
3628 uattr);
Martin KaFai Lau60197cf2018-04-18 15:56:02 -07003629 else if (f.file->f_op == &btf_fops)
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003630 err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003631 else if (f.file->f_op == &bpf_link_fops)
3632 err = bpf_link_get_info_by_fd(f.file->private_data,
3633 attr, uattr);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003634 else
3635 err = -EINVAL;
3636
3637 fdput(f);
3638 return err;
3639}
3640
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07003641#define BPF_BTF_LOAD_LAST_FIELD btf_log_level
3642
3643static int bpf_btf_load(const union bpf_attr *attr)
3644{
3645 if (CHECK_ATTR(BPF_BTF_LOAD))
3646 return -EINVAL;
3647
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07003648 if (!bpf_capable())
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07003649 return -EPERM;
3650
3651 return btf_new_fd(attr);
3652}
3653
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003654#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id
3655
3656static int bpf_btf_get_fd_by_id(const union bpf_attr *attr)
3657{
3658 if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID))
3659 return -EINVAL;
3660
3661 if (!capable(CAP_SYS_ADMIN))
3662 return -EPERM;
3663
3664 return btf_get_fd_by_id(attr->btf_id);
3665}
3666
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003667static int bpf_task_fd_query_copy(const union bpf_attr *attr,
3668 union bpf_attr __user *uattr,
3669 u32 prog_id, u32 fd_type,
3670 const char *buf, u64 probe_offset,
3671 u64 probe_addr)
3672{
3673 char __user *ubuf = u64_to_user_ptr(attr->task_fd_query.buf);
3674 u32 len = buf ? strlen(buf) : 0, input_len;
3675 int err = 0;
3676
3677 if (put_user(len, &uattr->task_fd_query.buf_len))
3678 return -EFAULT;
3679 input_len = attr->task_fd_query.buf_len;
3680 if (input_len && ubuf) {
3681 if (!len) {
3682 /* nothing to copy, just make ubuf NULL terminated */
3683 char zero = '\0';
3684
3685 if (put_user(zero, ubuf))
3686 return -EFAULT;
3687 } else if (input_len >= len + 1) {
3688 /* ubuf can hold the string with NULL terminator */
3689 if (copy_to_user(ubuf, buf, len + 1))
3690 return -EFAULT;
3691 } else {
3692 /* ubuf cannot hold the string with NULL terminator,
3693 * do a partial copy with NULL terminator.
3694 */
3695 char zero = '\0';
3696
3697 err = -ENOSPC;
3698 if (copy_to_user(ubuf, buf, input_len - 1))
3699 return -EFAULT;
3700 if (put_user(zero, ubuf + input_len - 1))
3701 return -EFAULT;
3702 }
3703 }
3704
3705 if (put_user(prog_id, &uattr->task_fd_query.prog_id) ||
3706 put_user(fd_type, &uattr->task_fd_query.fd_type) ||
3707 put_user(probe_offset, &uattr->task_fd_query.probe_offset) ||
3708 put_user(probe_addr, &uattr->task_fd_query.probe_addr))
3709 return -EFAULT;
3710
3711 return err;
3712}
3713
3714#define BPF_TASK_FD_QUERY_LAST_FIELD task_fd_query.probe_addr
3715
3716static int bpf_task_fd_query(const union bpf_attr *attr,
3717 union bpf_attr __user *uattr)
3718{
3719 pid_t pid = attr->task_fd_query.pid;
3720 u32 fd = attr->task_fd_query.fd;
3721 const struct perf_event *event;
3722 struct files_struct *files;
3723 struct task_struct *task;
3724 struct file *file;
3725 int err;
3726
3727 if (CHECK_ATTR(BPF_TASK_FD_QUERY))
3728 return -EINVAL;
3729
3730 if (!capable(CAP_SYS_ADMIN))
3731 return -EPERM;
3732
3733 if (attr->task_fd_query.flags != 0)
3734 return -EINVAL;
3735
3736 task = get_pid_task(find_vpid(pid), PIDTYPE_PID);
3737 if (!task)
3738 return -ENOENT;
3739
3740 files = get_files_struct(task);
3741 put_task_struct(task);
3742 if (!files)
3743 return -ENOENT;
3744
3745 err = 0;
3746 spin_lock(&files->file_lock);
3747 file = fcheck_files(files, fd);
3748 if (!file)
3749 err = -EBADF;
3750 else
3751 get_file(file);
3752 spin_unlock(&files->file_lock);
3753 put_files_struct(files);
3754
3755 if (err)
3756 goto out;
3757
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08003758 if (file->f_op == &bpf_link_fops) {
3759 struct bpf_link *link = file->private_data;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003760
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003761 if (link->ops == &bpf_raw_tp_link_lops) {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08003762 struct bpf_raw_tp_link *raw_tp =
3763 container_of(link, struct bpf_raw_tp_link, link);
3764 struct bpf_raw_event_map *btp = raw_tp->btp;
3765
3766 err = bpf_task_fd_query_copy(attr, uattr,
3767 raw_tp->link.prog->aux->id,
3768 BPF_FD_TYPE_RAW_TRACEPOINT,
3769 btp->tp->name, 0, 0);
3770 goto put_file;
3771 }
3772 goto out_not_supp;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003773 }
3774
3775 event = perf_get_event(file);
3776 if (!IS_ERR(event)) {
3777 u64 probe_offset, probe_addr;
3778 u32 prog_id, fd_type;
3779 const char *buf;
3780
3781 err = bpf_get_perf_event_info(event, &prog_id, &fd_type,
3782 &buf, &probe_offset,
3783 &probe_addr);
3784 if (!err)
3785 err = bpf_task_fd_query_copy(attr, uattr, prog_id,
3786 fd_type, buf,
3787 probe_offset,
3788 probe_addr);
3789 goto put_file;
3790 }
3791
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08003792out_not_supp:
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003793 err = -ENOTSUPP;
3794put_file:
3795 fput(file);
3796out:
3797 return err;
3798}
3799
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08003800#define BPF_MAP_BATCH_LAST_FIELD batch.flags
3801
3802#define BPF_DO_BATCH(fn) \
3803 do { \
3804 if (!fn) { \
3805 err = -ENOTSUPP; \
3806 goto err_put; \
3807 } \
3808 err = fn(map, attr, uattr); \
3809 } while (0)
3810
3811static int bpf_map_do_batch(const union bpf_attr *attr,
3812 union bpf_attr __user *uattr,
3813 int cmd)
3814{
3815 struct bpf_map *map;
3816 int err, ufd;
3817 struct fd f;
3818
3819 if (CHECK_ATTR(BPF_MAP_BATCH))
3820 return -EINVAL;
3821
3822 ufd = attr->batch.map_fd;
3823 f = fdget(ufd);
3824 map = __bpf_map_get(f);
3825 if (IS_ERR(map))
3826 return PTR_ERR(map);
3827
Yonghong Song05799632020-01-15 10:43:04 -08003828 if ((cmd == BPF_MAP_LOOKUP_BATCH ||
3829 cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH) &&
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08003830 !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
3831 err = -EPERM;
3832 goto err_put;
3833 }
3834
3835 if (cmd != BPF_MAP_LOOKUP_BATCH &&
3836 !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
3837 err = -EPERM;
3838 goto err_put;
3839 }
3840
3841 if (cmd == BPF_MAP_LOOKUP_BATCH)
3842 BPF_DO_BATCH(map->ops->map_lookup_batch);
Yonghong Song05799632020-01-15 10:43:04 -08003843 else if (cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH)
3844 BPF_DO_BATCH(map->ops->map_lookup_and_delete_batch);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08003845 else if (cmd == BPF_MAP_UPDATE_BATCH)
3846 BPF_DO_BATCH(map->ops->map_update_batch);
3847 else
3848 BPF_DO_BATCH(map->ops->map_delete_batch);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08003849
3850err_put:
3851 fdput(f);
3852 return err;
3853}
3854
Yonghong Songde4e05c2020-05-09 10:59:01 -07003855static int tracing_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
3856{
3857 if (attr->link_create.attach_type == BPF_TRACE_ITER &&
3858 prog->expected_attach_type == BPF_TRACE_ITER)
3859 return bpf_iter_link_attach(attr, prog);
3860
3861 return -EINVAL;
3862}
3863
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07003864#define BPF_LINK_CREATE_LAST_FIELD link_create.flags
3865static int link_create(union bpf_attr *attr)
3866{
3867 enum bpf_prog_type ptype;
3868 struct bpf_prog *prog;
3869 int ret;
3870
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07003871 if (CHECK_ATTR(BPF_LINK_CREATE))
3872 return -EINVAL;
3873
3874 ptype = attach_type_to_prog_type(attr->link_create.attach_type);
3875 if (ptype == BPF_PROG_TYPE_UNSPEC)
3876 return -EINVAL;
3877
3878 prog = bpf_prog_get_type(attr->link_create.prog_fd, ptype);
3879 if (IS_ERR(prog))
3880 return PTR_ERR(prog);
3881
3882 ret = bpf_prog_attach_check_attach_type(prog,
3883 attr->link_create.attach_type);
3884 if (ret)
3885 goto err_out;
3886
3887 switch (ptype) {
3888 case BPF_PROG_TYPE_CGROUP_SKB:
3889 case BPF_PROG_TYPE_CGROUP_SOCK:
3890 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3891 case BPF_PROG_TYPE_SOCK_OPS:
3892 case BPF_PROG_TYPE_CGROUP_DEVICE:
3893 case BPF_PROG_TYPE_CGROUP_SYSCTL:
3894 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3895 ret = cgroup_bpf_link_attach(attr, prog);
3896 break;
Yonghong Songde4e05c2020-05-09 10:59:01 -07003897 case BPF_PROG_TYPE_TRACING:
3898 ret = tracing_bpf_link_attach(attr, prog);
3899 break;
Jakub Sitnicki7f045a42020-05-31 10:28:38 +02003900 case BPF_PROG_TYPE_FLOW_DISSECTOR:
3901 ret = netns_bpf_link_create(attr, prog);
3902 break;
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07003903 default:
3904 ret = -EINVAL;
3905 }
3906
3907err_out:
3908 if (ret < 0)
3909 bpf_prog_put(prog);
3910 return ret;
3911}
3912
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07003913#define BPF_LINK_UPDATE_LAST_FIELD link_update.old_prog_fd
3914
3915static int link_update(union bpf_attr *attr)
3916{
3917 struct bpf_prog *old_prog = NULL, *new_prog;
3918 struct bpf_link *link;
3919 u32 flags;
3920 int ret;
3921
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07003922 if (CHECK_ATTR(BPF_LINK_UPDATE))
3923 return -EINVAL;
3924
3925 flags = attr->link_update.flags;
3926 if (flags & ~BPF_F_REPLACE)
3927 return -EINVAL;
3928
3929 link = bpf_link_get_from_fd(attr->link_update.link_fd);
3930 if (IS_ERR(link))
3931 return PTR_ERR(link);
3932
3933 new_prog = bpf_prog_get(attr->link_update.new_prog_fd);
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07003934 if (IS_ERR(new_prog)) {
3935 ret = PTR_ERR(new_prog);
3936 goto out_put_link;
3937 }
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07003938
3939 if (flags & BPF_F_REPLACE) {
3940 old_prog = bpf_prog_get(attr->link_update.old_prog_fd);
3941 if (IS_ERR(old_prog)) {
3942 ret = PTR_ERR(old_prog);
3943 old_prog = NULL;
3944 goto out_put_progs;
3945 }
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07003946 } else if (attr->link_update.old_prog_fd) {
3947 ret = -EINVAL;
3948 goto out_put_progs;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07003949 }
3950
Andrii Nakryikof9d04122020-04-28 17:16:05 -07003951 if (link->ops->update_prog)
3952 ret = link->ops->update_prog(link, new_prog, old_prog);
3953 else
Jakub Sitnickife537392020-05-25 14:29:28 +02003954 ret = -EINVAL;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07003955
3956out_put_progs:
3957 if (old_prog)
3958 bpf_prog_put(old_prog);
3959 if (ret)
3960 bpf_prog_put(new_prog);
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07003961out_put_link:
3962 bpf_link_put(link);
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07003963 return ret;
3964}
3965
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07003966static int bpf_link_inc_not_zero(struct bpf_link *link)
3967{
3968 return atomic64_fetch_add_unless(&link->refcnt, 1, 0) ? 0 : -ENOENT;
3969}
3970
3971#define BPF_LINK_GET_FD_BY_ID_LAST_FIELD link_id
3972
3973static int bpf_link_get_fd_by_id(const union bpf_attr *attr)
3974{
3975 struct bpf_link *link;
3976 u32 id = attr->link_id;
3977 int fd, err;
3978
3979 if (CHECK_ATTR(BPF_LINK_GET_FD_BY_ID))
3980 return -EINVAL;
3981
3982 if (!capable(CAP_SYS_ADMIN))
3983 return -EPERM;
3984
3985 spin_lock_bh(&link_idr_lock);
3986 link = idr_find(&link_idr, id);
3987 /* before link is "settled", ID is 0, pretend it doesn't exist yet */
3988 if (link) {
3989 if (link->id)
3990 err = bpf_link_inc_not_zero(link);
3991 else
3992 err = -EAGAIN;
3993 } else {
3994 err = -ENOENT;
3995 }
3996 spin_unlock_bh(&link_idr_lock);
3997
3998 if (err)
3999 return err;
4000
4001 fd = bpf_link_new_fd(link);
4002 if (fd < 0)
4003 bpf_link_put(link);
4004
4005 return fd;
4006}
4007
Song Liud46edd62020-04-30 00:15:04 -07004008DEFINE_MUTEX(bpf_stats_enabled_mutex);
4009
4010static int bpf_stats_release(struct inode *inode, struct file *file)
4011{
4012 mutex_lock(&bpf_stats_enabled_mutex);
4013 static_key_slow_dec(&bpf_stats_enabled_key.key);
4014 mutex_unlock(&bpf_stats_enabled_mutex);
4015 return 0;
4016}
4017
4018static const struct file_operations bpf_stats_fops = {
4019 .release = bpf_stats_release,
4020};
4021
4022static int bpf_enable_runtime_stats(void)
4023{
4024 int fd;
4025
4026 mutex_lock(&bpf_stats_enabled_mutex);
4027
4028 /* Set a very high limit to avoid overflow */
4029 if (static_key_count(&bpf_stats_enabled_key.key) > INT_MAX / 2) {
4030 mutex_unlock(&bpf_stats_enabled_mutex);
4031 return -EBUSY;
4032 }
4033
4034 fd = anon_inode_getfd("bpf-stats", &bpf_stats_fops, NULL, O_CLOEXEC);
4035 if (fd >= 0)
4036 static_key_slow_inc(&bpf_stats_enabled_key.key);
4037
4038 mutex_unlock(&bpf_stats_enabled_mutex);
4039 return fd;
4040}
4041
4042#define BPF_ENABLE_STATS_LAST_FIELD enable_stats.type
4043
4044static int bpf_enable_stats(union bpf_attr *attr)
4045{
4046
4047 if (CHECK_ATTR(BPF_ENABLE_STATS))
4048 return -EINVAL;
4049
4050 if (!capable(CAP_SYS_ADMIN))
4051 return -EPERM;
4052
4053 switch (attr->enable_stats.type) {
4054 case BPF_STATS_RUN_TIME:
4055 return bpf_enable_runtime_stats();
4056 default:
4057 break;
4058 }
4059 return -EINVAL;
4060}
4061
Yonghong Songac51d992020-05-09 10:59:05 -07004062#define BPF_ITER_CREATE_LAST_FIELD iter_create.flags
4063
4064static int bpf_iter_create(union bpf_attr *attr)
4065{
4066 struct bpf_link *link;
4067 int err;
4068
4069 if (CHECK_ATTR(BPF_ITER_CREATE))
4070 return -EINVAL;
4071
4072 if (attr->iter_create.flags)
4073 return -EINVAL;
4074
4075 link = bpf_link_get_from_fd(attr->iter_create.link_fd);
4076 if (IS_ERR(link))
4077 return PTR_ERR(link);
4078
4079 err = bpf_iter_new_fd(link);
4080 bpf_link_put(link);
4081
4082 return err;
4083}
4084
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004085SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
4086{
Greg Kroah-Hartman8096f222020-03-20 10:48:13 +01004087 union bpf_attr attr;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004088 int err;
4089
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07004090 if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004091 return -EPERM;
4092
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07004093 err = bpf_check_uarg_tail_zero(uattr, sizeof(attr), size);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004094 if (err)
4095 return err;
4096 size = min_t(u32, size, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004097
4098 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
Greg Kroah-Hartman8096f222020-03-20 10:48:13 +01004099 memset(&attr, 0, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004100 if (copy_from_user(&attr, uattr, size) != 0)
4101 return -EFAULT;
4102
Chenbo Fengafdb09c2017-10-18 13:00:24 -07004103 err = security_bpf(cmd, &attr, size);
4104 if (err < 0)
4105 return err;
4106
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004107 switch (cmd) {
4108 case BPF_MAP_CREATE:
4109 err = map_create(&attr);
4110 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07004111 case BPF_MAP_LOOKUP_ELEM:
4112 err = map_lookup_elem(&attr);
4113 break;
4114 case BPF_MAP_UPDATE_ELEM:
4115 err = map_update_elem(&attr);
4116 break;
4117 case BPF_MAP_DELETE_ELEM:
4118 err = map_delete_elem(&attr);
4119 break;
4120 case BPF_MAP_GET_NEXT_KEY:
4121 err = map_get_next_key(&attr);
4122 break;
Daniel Borkmann87df15d2019-04-09 23:20:06 +02004123 case BPF_MAP_FREEZE:
4124 err = map_freeze(&attr);
4125 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07004126 case BPF_PROG_LOAD:
Yonghong Song838e9692018-11-19 15:29:11 -08004127 err = bpf_prog_load(&attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07004128 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01004129 case BPF_OBJ_PIN:
4130 err = bpf_obj_pin(&attr);
4131 break;
4132 case BPF_OBJ_GET:
4133 err = bpf_obj_get(&attr);
4134 break;
Daniel Mackf4324552016-11-23 16:52:27 +01004135 case BPF_PROG_ATTACH:
4136 err = bpf_prog_attach(&attr);
4137 break;
4138 case BPF_PROG_DETACH:
4139 err = bpf_prog_detach(&attr);
4140 break;
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07004141 case BPF_PROG_QUERY:
4142 err = bpf_prog_query(&attr, uattr);
4143 break;
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07004144 case BPF_PROG_TEST_RUN:
4145 err = bpf_prog_test_run(&attr, uattr);
4146 break;
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07004147 case BPF_PROG_GET_NEXT_ID:
4148 err = bpf_obj_get_next_id(&attr, uattr,
4149 &prog_idr, &prog_idr_lock);
4150 break;
4151 case BPF_MAP_GET_NEXT_ID:
4152 err = bpf_obj_get_next_id(&attr, uattr,
4153 &map_idr, &map_idr_lock);
4154 break;
Quentin Monnet1b9ed842019-08-20 10:31:50 +01004155 case BPF_BTF_GET_NEXT_ID:
4156 err = bpf_obj_get_next_id(&attr, uattr,
4157 &btf_idr, &btf_idr_lock);
4158 break;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07004159 case BPF_PROG_GET_FD_BY_ID:
4160 err = bpf_prog_get_fd_by_id(&attr);
4161 break;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07004162 case BPF_MAP_GET_FD_BY_ID:
4163 err = bpf_map_get_fd_by_id(&attr);
4164 break;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004165 case BPF_OBJ_GET_INFO_BY_FD:
4166 err = bpf_obj_get_info_by_fd(&attr, uattr);
4167 break;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07004168 case BPF_RAW_TRACEPOINT_OPEN:
4169 err = bpf_raw_tracepoint_open(&attr);
4170 break;
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004171 case BPF_BTF_LOAD:
4172 err = bpf_btf_load(&attr);
4173 break;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07004174 case BPF_BTF_GET_FD_BY_ID:
4175 err = bpf_btf_get_fd_by_id(&attr);
4176 break;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004177 case BPF_TASK_FD_QUERY:
4178 err = bpf_task_fd_query(&attr, uattr);
4179 break;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02004180 case BPF_MAP_LOOKUP_AND_DELETE_ELEM:
4181 err = map_lookup_and_delete_elem(&attr);
4182 break;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004183 case BPF_MAP_LOOKUP_BATCH:
4184 err = bpf_map_do_batch(&attr, uattr, BPF_MAP_LOOKUP_BATCH);
4185 break;
Yonghong Song05799632020-01-15 10:43:04 -08004186 case BPF_MAP_LOOKUP_AND_DELETE_BATCH:
4187 err = bpf_map_do_batch(&attr, uattr,
4188 BPF_MAP_LOOKUP_AND_DELETE_BATCH);
4189 break;
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004190 case BPF_MAP_UPDATE_BATCH:
4191 err = bpf_map_do_batch(&attr, uattr, BPF_MAP_UPDATE_BATCH);
4192 break;
4193 case BPF_MAP_DELETE_BATCH:
4194 err = bpf_map_do_batch(&attr, uattr, BPF_MAP_DELETE_BATCH);
4195 break;
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004196 case BPF_LINK_CREATE:
4197 err = link_create(&attr);
4198 break;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004199 case BPF_LINK_UPDATE:
4200 err = link_update(&attr);
4201 break;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004202 case BPF_LINK_GET_FD_BY_ID:
4203 err = bpf_link_get_fd_by_id(&attr);
4204 break;
4205 case BPF_LINK_GET_NEXT_ID:
4206 err = bpf_obj_get_next_id(&attr, uattr,
4207 &link_idr, &link_idr_lock);
4208 break;
Song Liud46edd62020-04-30 00:15:04 -07004209 case BPF_ENABLE_STATS:
4210 err = bpf_enable_stats(&attr);
4211 break;
Yonghong Songac51d992020-05-09 10:59:05 -07004212 case BPF_ITER_CREATE:
4213 err = bpf_iter_create(&attr);
4214 break;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004215 default:
4216 err = -EINVAL;
4217 break;
4218 }
4219
4220 return err;
4221}