blob: f7c2c6354add944917da1baabcb11a10dfb0bf9f [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>
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02007#include <linux/bpf_verifier.h>
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07008#include <linux/btf.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07009#include <linux/syscalls.h>
10#include <linux/slab.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010011#include <linux/sched/signal.h>
Daniel Borkmannd407bd22017-01-18 15:14:17 +010012#include <linux/vmalloc.h>
13#include <linux/mmzone.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070014#include <linux/anon_inodes.h>
Yonghong Song41bdc4b2018-05-24 11:21:09 -070015#include <linux/fdtable.h>
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -070016#include <linux/file.h>
Yonghong Song41bdc4b2018-05-24 11:21:09 -070017#include <linux/fs.h>
Alexei Starovoitov09756af2014-09-26 00:17:00 -070018#include <linux/license.h>
19#include <linux/filter.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>
Mike Rapoportca5999f2020-06-08 21:32:38 -070028#include <linux/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 Starovoitov1e6c62a2020-08-27 15:01:11 -070032#include <linux/rcupdate_trace.h>
Roman Gushchin48edc1f2020-12-01 13:58:32 -080033#include <linux/memcontrol.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070034
Daniel Borkmannda765a22019-11-22 21:07:58 +010035#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
36 (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
37 (map)->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
38#define IS_FD_PROG_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY)
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070039#define IS_FD_HASH(map) ((map)->map_type == BPF_MAP_TYPE_HASH_OF_MAPS)
Daniel Borkmannda765a22019-11-22 21:07:58 +010040#define IS_FD_MAP(map) (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map) || \
41 IS_FD_HASH(map))
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070042
Chenbo Feng6e71b042017-10-18 13:00:22 -070043#define BPF_OBJ_FLAG_MASK (BPF_F_RDONLY | BPF_F_WRONLY)
44
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080045DEFINE_PER_CPU(int, bpf_prog_active);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070046static DEFINE_IDR(prog_idr);
47static DEFINE_SPINLOCK(prog_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -070048static DEFINE_IDR(map_idr);
49static DEFINE_SPINLOCK(map_idr_lock);
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -070050static DEFINE_IDR(link_idr);
51static DEFINE_SPINLOCK(link_idr_lock);
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080052
Daniel Borkmann08389d82021-05-11 22:35:17 +020053int sysctl_unprivileged_bpf_disabled __read_mostly =
54 IS_BUILTIN(CONFIG_BPF_UNPRIV_DEFAULT_OFF) ? 2 : 0;
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070055
Johannes Berg40077e02017-04-11 15:34:58 +020056static const struct bpf_map_ops * const bpf_map_types[] = {
Alexei Starovoitov91cc1a92019-11-14 10:57:15 -080057#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
Johannes Berg40077e02017-04-11 15:34:58 +020058#define BPF_MAP_TYPE(_id, _ops) \
59 [_id] = &_ops,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -070060#define BPF_LINK_TYPE(_id, _name)
Johannes Berg40077e02017-04-11 15:34:58 +020061#include <linux/bpf_types.h>
62#undef BPF_PROG_TYPE
63#undef BPF_MAP_TYPE
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -070064#undef BPF_LINK_TYPE
Johannes Berg40077e02017-04-11 15:34:58 +020065};
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070066
Mickaël Salaün752ba562017-08-07 20:45:20 +020067/*
68 * If we're handed a bigger struct than we know of, ensure all the unknown bits
69 * are 0 - i.e. new user-space does not rely on any kernel feature extensions
70 * we don't know about yet.
71 *
72 * There is a ToCToU between this function call and the following
73 * copy_from_user() call. However, this is not a concern since this function is
74 * meant to be a future-proofing of bits.
75 */
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -070076int bpf_check_uarg_tail_zero(bpfptr_t uaddr,
Martin KaFai Laudcab51f2018-05-22 15:03:31 -070077 size_t expected_size,
78 size_t actual_size)
Mickaël Salaün58291a72017-08-07 20:45:19 +020079{
Al Virob7e4b652020-05-08 00:16:31 -040080 int res;
Mickaël Salaün58291a72017-08-07 20:45:19 +020081
Mickaël Salaün752ba562017-08-07 20:45:20 +020082 if (unlikely(actual_size > PAGE_SIZE)) /* silly large */
83 return -E2BIG;
84
Mickaël Salaün58291a72017-08-07 20:45:19 +020085 if (actual_size <= expected_size)
86 return 0;
87
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -070088 if (uaddr.is_kernel)
89 res = memchr_inv(uaddr.kernel + expected_size, 0,
90 actual_size - expected_size) == NULL;
91 else
92 res = check_zeroed_user(uaddr.user + expected_size,
93 actual_size - expected_size);
Al Virob7e4b652020-05-08 00:16:31 -040094 if (res < 0)
95 return res;
96 return res ? 0 : -E2BIG;
Mickaël Salaün58291a72017-08-07 20:45:19 +020097}
98
Jakub Kicinskia3884572018-01-11 20:29:09 -080099const struct bpf_map_ops bpf_map_offload_ops = {
Martin KaFai Lauf4d05252020-08-27 18:18:06 -0700100 .map_meta_equal = bpf_map_meta_equal,
Jakub Kicinskia3884572018-01-11 20:29:09 -0800101 .map_alloc = bpf_map_offload_map_alloc,
102 .map_free = bpf_map_offload_map_free,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200103 .map_check_btf = map_check_no_btf,
Jakub Kicinskia3884572018-01-11 20:29:09 -0800104};
105
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700106static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
107{
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800108 const struct bpf_map_ops *ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100109 u32 type = attr->map_type;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700110 struct bpf_map *map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800111 int err;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700112
Mark Rutland9ef09e32018-05-03 17:04:59 +0100113 if (type >= ARRAY_SIZE(bpf_map_types))
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800114 return ERR_PTR(-EINVAL);
Mark Rutland9ef09e32018-05-03 17:04:59 +0100115 type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types));
116 ops = bpf_map_types[type];
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800117 if (!ops)
Johannes Berg40077e02017-04-11 15:34:58 +0200118 return ERR_PTR(-EINVAL);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700119
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800120 if (ops->map_alloc_check) {
121 err = ops->map_alloc_check(attr);
122 if (err)
123 return ERR_PTR(err);
124 }
Jakub Kicinskia3884572018-01-11 20:29:09 -0800125 if (attr->map_ifindex)
126 ops = &bpf_map_offload_ops;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800127 map = ops->map_alloc(attr);
Johannes Berg40077e02017-04-11 15:34:58 +0200128 if (IS_ERR(map))
129 return map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800130 map->ops = ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100131 map->map_type = type;
Johannes Berg40077e02017-04-11 15:34:58 +0200132 return map;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700133}
134
Roman Gushchin80ee81e2020-12-01 13:58:58 -0800135static u32 bpf_map_value_size(const struct bpf_map *map)
Brian Vazquez15c14a32020-01-15 10:43:00 -0800136{
137 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
138 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
139 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
140 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
141 return round_up(map->value_size, 8) * num_possible_cpus();
142 else if (IS_FD_MAP(map))
143 return sizeof(u32);
144 else
145 return map->value_size;
146}
147
148static void maybe_wait_bpf_programs(struct bpf_map *map)
149{
150 /* Wait for any running BPF programs to complete so that
151 * userspace, when we return to it, knows that all programs
152 * that could be running use the new map value.
153 */
154 if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
155 map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
156 synchronize_rcu();
157}
158
159static int bpf_map_update_value(struct bpf_map *map, struct fd f, void *key,
160 void *value, __u64 flags)
161{
162 int err;
163
164 /* Need to create a kthread, thus must support schedule */
165 if (bpf_map_is_dev_bound(map)) {
166 return bpf_map_offload_update_elem(map, key, value, flags);
167 } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
Brian Vazquez15c14a32020-01-15 10:43:00 -0800168 map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
169 return map->ops->map_update_elem(map, key, value, flags);
Lorenz Bauer13b79d32020-08-21 11:29:45 +0100170 } else if (map->map_type == BPF_MAP_TYPE_SOCKHASH ||
171 map->map_type == BPF_MAP_TYPE_SOCKMAP) {
172 return sock_map_update_elem_sys(map, key, value, flags);
Brian Vazquez15c14a32020-01-15 10:43:00 -0800173 } else if (IS_FD_PROG_ARRAY(map)) {
174 return bpf_fd_array_map_update_elem(map, f.file, key, value,
175 flags);
176 }
177
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100178 bpf_disable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800179 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
180 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
181 err = bpf_percpu_hash_update(map, key, value, flags);
182 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
183 err = bpf_percpu_array_update(map, key, value, flags);
184 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
185 err = bpf_percpu_cgroup_storage_update(map, key, value,
186 flags);
187 } else if (IS_FD_ARRAY(map)) {
188 rcu_read_lock();
189 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
190 flags);
191 rcu_read_unlock();
192 } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
193 rcu_read_lock();
194 err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
195 flags);
196 rcu_read_unlock();
197 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
198 /* rcu_read_lock() is not needed */
199 err = bpf_fd_reuseport_array_update_elem(map, key, value,
200 flags);
201 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
Joanne Koong93309862021-10-27 16:45:00 -0700202 map->map_type == BPF_MAP_TYPE_STACK ||
203 map->map_type == BPF_MAP_TYPE_BLOOM_FILTER) {
Brian Vazquez15c14a32020-01-15 10:43:00 -0800204 err = map->ops->map_push_elem(map, value, flags);
205 } else {
206 rcu_read_lock();
207 err = map->ops->map_update_elem(map, key, value, flags);
208 rcu_read_unlock();
209 }
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100210 bpf_enable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800211 maybe_wait_bpf_programs(map);
212
213 return err;
214}
215
216static int bpf_map_copy_value(struct bpf_map *map, void *key, void *value,
217 __u64 flags)
218{
219 void *ptr;
220 int err;
221
Brian Vazquezcb4d03a2020-01-15 10:43:01 -0800222 if (bpf_map_is_dev_bound(map))
223 return bpf_map_offload_lookup_elem(map, key, value);
Brian Vazquez15c14a32020-01-15 10:43:00 -0800224
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100225 bpf_disable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800226 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
227 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
228 err = bpf_percpu_hash_copy(map, key, value);
229 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
230 err = bpf_percpu_array_copy(map, key, value);
231 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
232 err = bpf_percpu_cgroup_storage_copy(map, key, value);
233 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
234 err = bpf_stackmap_copy(map, key, value);
235 } else if (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map)) {
236 err = bpf_fd_array_map_lookup_elem(map, key, value);
237 } else if (IS_FD_HASH(map)) {
238 err = bpf_fd_htab_map_lookup_elem(map, key, value);
239 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
240 err = bpf_fd_reuseport_array_lookup_elem(map, key, value);
241 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
Joanne Koong93309862021-10-27 16:45:00 -0700242 map->map_type == BPF_MAP_TYPE_STACK ||
243 map->map_type == BPF_MAP_TYPE_BLOOM_FILTER) {
Brian Vazquez15c14a32020-01-15 10:43:00 -0800244 err = map->ops->map_peek_elem(map, value);
245 } else if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
246 /* struct_ops map requires directly updating "value" */
247 err = bpf_struct_ops_map_sys_lookup_elem(map, key, value);
248 } else {
249 rcu_read_lock();
250 if (map->ops->map_lookup_elem_sys_only)
251 ptr = map->ops->map_lookup_elem_sys_only(map, key);
252 else
253 ptr = map->ops->map_lookup_elem(map, key);
254 if (IS_ERR(ptr)) {
255 err = PTR_ERR(ptr);
256 } else if (!ptr) {
257 err = -ENOENT;
258 } else {
259 err = 0;
260 if (flags & BPF_F_LOCK)
261 /* lock 'ptr' and copy everything but lock */
262 copy_map_value_locked(map, value, ptr, true);
263 else
264 copy_map_value(map, value, ptr);
Alexei Starovoitov68134662021-07-14 17:54:10 -0700265 /* mask lock and timer, since value wasn't zero inited */
266 check_and_init_map_value(map, value);
Brian Vazquez15c14a32020-01-15 10:43:00 -0800267 }
268 rcu_read_unlock();
269 }
270
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100271 bpf_enable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800272 maybe_wait_bpf_programs(map);
273
274 return err;
275}
276
Roman Gushchind5299b62020-12-01 13:58:33 -0800277/* Please, do not use this function outside from the map creation path
278 * (e.g. in map update path) without taking care of setting the active
279 * memory cgroup (see at bpf_map_kmalloc_node() for example).
280 */
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100281static void *__bpf_map_area_alloc(u64 size, int numa_node, bool mmapable)
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100282{
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100283 /* We really just want to fail instead of triggering OOM killer
284 * under memory pressure, therefore we set __GFP_NORETRY to kmalloc,
285 * which is used for lower order allocation requests.
286 *
287 * It has been observed that higher order allocation requests done by
288 * vmalloc with __GFP_NORETRY being set might fail due to not trying
289 * to reclaim memory from the page cache, thus we set
290 * __GFP_RETRY_MAYFAIL to avoid such situations.
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100291 */
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100292
Roman Gushchind5299b62020-12-01 13:58:33 -0800293 const gfp_t gfp = __GFP_NOWARN | __GFP_ZERO | __GFP_ACCOUNT;
Christoph Hellwig041de932020-06-01 21:52:02 -0700294 unsigned int flags = 0;
295 unsigned long align = 1;
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100296 void *area;
297
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100298 if (size >= SIZE_MAX)
299 return NULL;
300
Andrii Nakryikofc970222019-11-17 09:28:04 -0800301 /* kmalloc()'ed memory can't be mmap()'ed */
Christoph Hellwig041de932020-06-01 21:52:02 -0700302 if (mmapable) {
303 BUG_ON(!PAGE_ALIGNED(size));
304 align = SHMLBA;
305 flags = VM_USERMAP;
306 } else if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
307 area = kmalloc_node(size, gfp | GFP_USER | __GFP_NORETRY,
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100308 numa_node);
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100309 if (area != NULL)
310 return area;
311 }
Christoph Hellwig041de932020-06-01 21:52:02 -0700312
313 return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
314 gfp | GFP_KERNEL | __GFP_RETRY_MAYFAIL, PAGE_KERNEL,
315 flags, numa_node, __builtin_return_address(0));
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100316}
317
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100318void *bpf_map_area_alloc(u64 size, int numa_node)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800319{
320 return __bpf_map_area_alloc(size, numa_node, false);
321}
322
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100323void *bpf_map_area_mmapable_alloc(u64 size, int numa_node)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800324{
325 return __bpf_map_area_alloc(size, numa_node, true);
326}
327
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100328void bpf_map_area_free(void *area)
329{
330 kvfree(area);
331}
332
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200333static u32 bpf_map_flags_retain_permanent(u32 flags)
334{
335 /* Some map creation flags are not tied to the map object but
336 * rather to the map fd instead, so they have no meaning upon
337 * map object inspection since multiple file descriptors with
338 * different (access) properties can exist here. Thus, given
339 * this has zero meaning for the map itself, lets clear these
340 * from here.
341 */
342 return flags & ~(BPF_F_RDONLY | BPF_F_WRONLY);
343}
344
Jakub Kicinskibd475642018-01-11 20:29:06 -0800345void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr)
346{
347 map->map_type = attr->map_type;
348 map->key_size = attr->key_size;
349 map->value_size = attr->value_size;
350 map->max_entries = attr->max_entries;
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200351 map->map_flags = bpf_map_flags_retain_permanent(attr->map_flags);
Jakub Kicinskibd475642018-01-11 20:29:06 -0800352 map->numa_node = bpf_map_attr_numa_node(attr);
Joanne Koong93309862021-10-27 16:45:00 -0700353 map->map_extra = attr->map_extra;
Jakub Kicinskibd475642018-01-11 20:29:06 -0800354}
355
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700356static int bpf_map_alloc_id(struct bpf_map *map)
357{
358 int id;
359
Shaohua Lib76354c2018-03-27 11:53:21 -0700360 idr_preload(GFP_KERNEL);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700361 spin_lock_bh(&map_idr_lock);
362 id = idr_alloc_cyclic(&map_idr, map, 1, INT_MAX, GFP_ATOMIC);
363 if (id > 0)
364 map->id = id;
365 spin_unlock_bh(&map_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -0700366 idr_preload_end();
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700367
368 if (WARN_ON_ONCE(!id))
369 return -ENOSPC;
370
371 return id > 0 ? 0 : id;
372}
373
Jakub Kicinskia3884572018-01-11 20:29:09 -0800374void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700375{
Eric Dumazet930651a2017-09-19 09:15:59 -0700376 unsigned long flags;
377
Jakub Kicinskia3884572018-01-11 20:29:09 -0800378 /* Offloaded maps are removed from the IDR store when their device
379 * disappears - even if someone holds an fd to them they are unusable,
380 * the memory is gone, all ops will fail; they are simply waiting for
381 * refcnt to drop to be freed.
382 */
383 if (!map->id)
384 return;
385
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700386 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700387 spin_lock_irqsave(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700388 else
389 __acquire(&map_idr_lock);
390
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700391 idr_remove(&map_idr, map->id);
Jakub Kicinskia3884572018-01-11 20:29:09 -0800392 map->id = 0;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700393
394 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700395 spin_unlock_irqrestore(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700396 else
397 __release(&map_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700398}
399
Roman Gushchin48edc1f2020-12-01 13:58:32 -0800400#ifdef CONFIG_MEMCG_KMEM
401static void bpf_map_save_memcg(struct bpf_map *map)
402{
403 map->memcg = get_mem_cgroup_from_mm(current->mm);
404}
405
406static void bpf_map_release_memcg(struct bpf_map *map)
407{
408 mem_cgroup_put(map->memcg);
409}
410
411void *bpf_map_kmalloc_node(const struct bpf_map *map, size_t size, gfp_t flags,
412 int node)
413{
414 struct mem_cgroup *old_memcg;
415 void *ptr;
416
417 old_memcg = set_active_memcg(map->memcg);
418 ptr = kmalloc_node(size, flags | __GFP_ACCOUNT, node);
419 set_active_memcg(old_memcg);
420
421 return ptr;
422}
423
424void *bpf_map_kzalloc(const struct bpf_map *map, size_t size, gfp_t flags)
425{
426 struct mem_cgroup *old_memcg;
427 void *ptr;
428
429 old_memcg = set_active_memcg(map->memcg);
430 ptr = kzalloc(size, flags | __GFP_ACCOUNT);
431 set_active_memcg(old_memcg);
432
433 return ptr;
434}
435
436void __percpu *bpf_map_alloc_percpu(const struct bpf_map *map, size_t size,
437 size_t align, gfp_t flags)
438{
439 struct mem_cgroup *old_memcg;
440 void __percpu *ptr;
441
442 old_memcg = set_active_memcg(map->memcg);
443 ptr = __alloc_percpu_gfp(size, align, flags | __GFP_ACCOUNT);
444 set_active_memcg(old_memcg);
445
446 return ptr;
447}
448
449#else
450static void bpf_map_save_memcg(struct bpf_map *map)
451{
452}
453
454static void bpf_map_release_memcg(struct bpf_map *map)
455{
456}
457#endif
458
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700459/* called from workqueue */
460static void bpf_map_free_deferred(struct work_struct *work)
461{
462 struct bpf_map *map = container_of(work, struct bpf_map, work);
463
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700464 security_bpf_map_free(map);
Roman Gushchin48edc1f2020-12-01 13:58:32 -0800465 bpf_map_release_memcg(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700466 /* implementation dependent freeing */
467 map->ops->map_free(map);
468}
469
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100470static void bpf_map_put_uref(struct bpf_map *map)
471{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800472 if (atomic64_dec_and_test(&map->usercnt)) {
John Fastabendba6b8de2018-04-23 15:39:23 -0700473 if (map->ops->map_release_uref)
474 map->ops->map_release_uref(map);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100475 }
476}
477
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700478/* decrement map refcnt and schedule it for freeing via workqueue
479 * (unrelying map implementation ops->map_free() might sleep)
480 */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700481static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700482{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800483 if (atomic64_dec_and_test(&map->refcnt)) {
Martin KaFai Lau34ad5582017-06-05 12:15:48 -0700484 /* bpf_map_free_id() must be called first */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700485 bpf_map_free_id(map, do_idr_lock);
Martin KaFai Lau78958fc2018-05-04 14:49:51 -0700486 btf_put(map->btf);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700487 INIT_WORK(&map->work, bpf_map_free_deferred);
488 schedule_work(&map->work);
489 }
490}
491
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700492void bpf_map_put(struct bpf_map *map)
493{
494 __bpf_map_put(map, true);
495}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700496EXPORT_SYMBOL_GPL(bpf_map_put);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700497
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100498void bpf_map_put_with_uref(struct bpf_map *map)
499{
500 bpf_map_put_uref(map);
501 bpf_map_put(map);
502}
503
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700504static int bpf_map_release(struct inode *inode, struct file *filp)
505{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200506 struct bpf_map *map = filp->private_data;
507
508 if (map->ops->map_release)
509 map->ops->map_release(map, filp);
510
511 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700512 return 0;
513}
514
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200515static fmode_t map_get_sys_perms(struct bpf_map *map, struct fd f)
516{
517 fmode_t mode = f.file->f_mode;
518
519 /* Our file permissions may have been overridden by global
520 * map permissions facing syscall side.
521 */
522 if (READ_ONCE(map->frozen))
523 mode &= ~FMODE_CAN_WRITE;
524 return mode;
525}
526
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100527#ifdef CONFIG_PROC_FS
Roman Gushchin80ee81e2020-12-01 13:58:58 -0800528/* Provides an approximation of the map's memory footprint.
529 * Used only to provide a backward compatibility and display
530 * a reasonable "memlock" info.
531 */
532static unsigned long bpf_map_memory_footprint(const struct bpf_map *map)
533{
534 unsigned long size;
535
536 size = round_up(map->key_size + bpf_map_value_size(map), 8);
537
538 return round_up(map->max_entries * size, PAGE_SIZE);
539}
540
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100541static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
542{
543 const struct bpf_map *map = filp->private_data;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100544 const struct bpf_array *array;
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100545 u32 type = 0, jited = 0;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100546
547 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
548 array = container_of(map, struct bpf_array, map);
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100549 type = array->aux->type;
550 jited = array->aux->jited;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100551 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100552
553 seq_printf(m,
554 "map_type:\t%u\n"
555 "key_size:\t%u\n"
556 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100557 "max_entries:\t%u\n"
Daniel Borkmann21116b72016-11-26 01:28:07 +0100558 "map_flags:\t%#x\n"
Joanne Koong93309862021-10-27 16:45:00 -0700559 "map_extra:\t%#llx\n"
Roman Gushchin80ee81e2020-12-01 13:58:58 -0800560 "memlock:\t%lu\n"
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200561 "map_id:\t%u\n"
562 "frozen:\t%u\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100563 map->map_type,
564 map->key_size,
565 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100566 map->max_entries,
Daniel Borkmann21116b72016-11-26 01:28:07 +0100567 map->map_flags,
Joanne Koong93309862021-10-27 16:45:00 -0700568 (unsigned long long)map->map_extra,
Roman Gushchin80ee81e2020-12-01 13:58:58 -0800569 bpf_map_memory_footprint(map),
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200570 map->id,
571 READ_ONCE(map->frozen));
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100572 if (type) {
573 seq_printf(m, "owner_prog_type:\t%u\n", type);
574 seq_printf(m, "owner_jited:\t%u\n", jited);
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200575 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100576}
577#endif
578
Chenbo Feng6e71b042017-10-18 13:00:22 -0700579static ssize_t bpf_dummy_read(struct file *filp, char __user *buf, size_t siz,
580 loff_t *ppos)
581{
582 /* We need this handler such that alloc_file() enables
583 * f_mode with FMODE_CAN_READ.
584 */
585 return -EINVAL;
586}
587
588static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
589 size_t siz, loff_t *ppos)
590{
591 /* We need this handler such that alloc_file() enables
592 * f_mode with FMODE_CAN_WRITE.
593 */
594 return -EINVAL;
595}
596
Andrii Nakryikofc970222019-11-17 09:28:04 -0800597/* called for any extra memory-mapped regions (except initial) */
598static void bpf_map_mmap_open(struct vm_area_struct *vma)
599{
600 struct bpf_map *map = vma->vm_file->private_data;
601
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700602 if (vma->vm_flags & VM_MAYWRITE) {
Andrii Nakryikofc970222019-11-17 09:28:04 -0800603 mutex_lock(&map->freeze_mutex);
604 map->writecnt++;
605 mutex_unlock(&map->freeze_mutex);
606 }
607}
608
609/* called for all unmapped memory region (including initial) */
610static void bpf_map_mmap_close(struct vm_area_struct *vma)
611{
612 struct bpf_map *map = vma->vm_file->private_data;
613
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700614 if (vma->vm_flags & VM_MAYWRITE) {
Andrii Nakryikofc970222019-11-17 09:28:04 -0800615 mutex_lock(&map->freeze_mutex);
616 map->writecnt--;
617 mutex_unlock(&map->freeze_mutex);
618 }
Andrii Nakryikofc970222019-11-17 09:28:04 -0800619}
620
621static const struct vm_operations_struct bpf_map_default_vmops = {
622 .open = bpf_map_mmap_open,
623 .close = bpf_map_mmap_close,
624};
625
626static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
627{
628 struct bpf_map *map = filp->private_data;
629 int err;
630
Alexei Starovoitov68134662021-07-14 17:54:10 -0700631 if (!map->ops->map_mmap || map_value_has_spin_lock(map) ||
632 map_value_has_timer(map))
Andrii Nakryikofc970222019-11-17 09:28:04 -0800633 return -ENOTSUPP;
634
635 if (!(vma->vm_flags & VM_SHARED))
636 return -EINVAL;
637
638 mutex_lock(&map->freeze_mutex);
639
Andrii Nakryikodfeb3762020-05-18 22:38:24 -0700640 if (vma->vm_flags & VM_WRITE) {
641 if (map->frozen) {
642 err = -EPERM;
643 goto out;
644 }
645 /* map is meant to be read-only, so do not allow mapping as
646 * writable, because it's possible to leak a writable page
647 * reference and allows user-space to still modify it after
648 * freezing, while verifier will assume contents do not change
649 */
650 if (map->map_flags & BPF_F_RDONLY_PROG) {
651 err = -EACCES;
652 goto out;
653 }
Andrii Nakryikofc970222019-11-17 09:28:04 -0800654 }
655
656 /* set default open/close callbacks */
657 vma->vm_ops = &bpf_map_default_vmops;
658 vma->vm_private_data = map;
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700659 vma->vm_flags &= ~VM_MAYEXEC;
660 if (!(vma->vm_flags & VM_WRITE))
661 /* disallow re-mapping with PROT_WRITE */
662 vma->vm_flags &= ~VM_MAYWRITE;
Andrii Nakryikofc970222019-11-17 09:28:04 -0800663
664 err = map->ops->map_mmap(map, vma);
665 if (err)
666 goto out;
667
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700668 if (vma->vm_flags & VM_MAYWRITE)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800669 map->writecnt++;
670out:
671 mutex_unlock(&map->freeze_mutex);
672 return err;
673}
674
Andrii Nakryiko457f4432020-05-29 00:54:20 -0700675static __poll_t bpf_map_poll(struct file *filp, struct poll_table_struct *pts)
676{
677 struct bpf_map *map = filp->private_data;
678
679 if (map->ops->map_poll)
680 return map->ops->map_poll(map, filp, pts);
681
682 return EPOLLERR;
683}
684
Chenbo Fengf66e4482017-10-18 13:00:26 -0700685const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100686#ifdef CONFIG_PROC_FS
687 .show_fdinfo = bpf_map_show_fdinfo,
688#endif
689 .release = bpf_map_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700690 .read = bpf_dummy_read,
691 .write = bpf_dummy_write,
Andrii Nakryikofc970222019-11-17 09:28:04 -0800692 .mmap = bpf_map_mmap,
Andrii Nakryiko457f4432020-05-29 00:54:20 -0700693 .poll = bpf_map_poll,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700694};
695
Chenbo Feng6e71b042017-10-18 13:00:22 -0700696int bpf_map_new_fd(struct bpf_map *map, int flags)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100697{
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700698 int ret;
699
700 ret = security_bpf_map(map, OPEN_FMODE(flags));
701 if (ret < 0)
702 return ret;
703
Daniel Borkmannaa797812015-10-29 14:58:06 +0100704 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700705 flags | O_CLOEXEC);
706}
707
708int bpf_get_file_flag(int flags)
709{
710 if ((flags & BPF_F_RDONLY) && (flags & BPF_F_WRONLY))
711 return -EINVAL;
712 if (flags & BPF_F_RDONLY)
713 return O_RDONLY;
714 if (flags & BPF_F_WRONLY)
715 return O_WRONLY;
716 return O_RDWR;
Daniel Borkmannaa797812015-10-29 14:58:06 +0100717}
718
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700719/* helper macro to check that unused fields 'union bpf_attr' are zero */
720#define CHECK_ATTR(CMD) \
721 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
722 sizeof(attr->CMD##_LAST_FIELD), 0, \
723 sizeof(*attr) - \
724 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
725 sizeof(attr->CMD##_LAST_FIELD)) != NULL
726
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700727/* dst and src must have at least "size" number of bytes.
728 * Return strlen on success and < 0 on error.
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700729 */
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700730int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size)
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700731{
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700732 const char *end = src + size;
733 const char *orig_src = src;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700734
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700735 memset(dst, 0, size);
Daniel Borkmann3e0ddc4f2019-04-09 23:20:07 +0200736 /* Copy all isalnum(), '_' and '.' chars. */
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700737 while (src < end && *src) {
Daniel Borkmann3e0ddc4f2019-04-09 23:20:07 +0200738 if (!isalnum(*src) &&
739 *src != '_' && *src != '.')
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700740 return -EINVAL;
741 *dst++ = *src++;
742 }
743
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700744 /* No '\0' found in "size" number of bytes */
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700745 if (src == end)
746 return -EINVAL;
747
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700748 return src - orig_src;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700749}
750
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200751int map_check_no_btf(const struct bpf_map *map,
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800752 const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200753 const struct btf_type *key_type,
754 const struct btf_type *value_type)
755{
756 return -ENOTSUPP;
757}
758
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800759static int map_check_btf(struct bpf_map *map, const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200760 u32 btf_key_id, u32 btf_value_id)
761{
762 const struct btf_type *key_type, *value_type;
763 u32 key_size, value_size;
764 int ret = 0;
765
Daniel Borkmann2824ecb2019-04-09 23:20:10 +0200766 /* Some maps allow key to be unspecified. */
767 if (btf_key_id) {
768 key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
769 if (!key_type || key_size != map->key_size)
770 return -EINVAL;
771 } else {
772 key_type = btf_type_by_id(btf, 0);
773 if (!map->ops->map_check_btf)
774 return -EINVAL;
775 }
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200776
777 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
778 if (!value_type || value_size != map->value_size)
779 return -EINVAL;
780
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800781 map->spin_lock_off = btf_find_spin_lock(btf, value_type);
782
783 if (map_value_has_spin_lock(map)) {
Daniel Borkmann591fe982019-04-09 23:20:05 +0200784 if (map->map_flags & BPF_F_RDONLY_PROG)
785 return -EACCES;
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800786 if (map->map_type != BPF_MAP_TYPE_HASH &&
Alexei Starovoitove16d2f12019-01-31 15:40:05 -0800787 map->map_type != BPF_MAP_TYPE_ARRAY &&
Martin KaFai Lau6ac99e82019-04-26 16:39:39 -0700788 map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE &&
KP Singh8ea63682020-08-25 20:29:17 +0200789 map->map_type != BPF_MAP_TYPE_SK_STORAGE &&
KP Singh4cf1bc12020-11-06 10:37:40 +0000790 map->map_type != BPF_MAP_TYPE_INODE_STORAGE &&
791 map->map_type != BPF_MAP_TYPE_TASK_STORAGE)
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800792 return -ENOTSUPP;
793 if (map->spin_lock_off + sizeof(struct bpf_spin_lock) >
794 map->value_size) {
795 WARN_ONCE(1,
796 "verifier bug spin_lock_off %d value_size %d\n",
797 map->spin_lock_off, map->value_size);
798 return -EFAULT;
799 }
800 }
801
Alexei Starovoitov68134662021-07-14 17:54:10 -0700802 map->timer_off = btf_find_timer(btf, value_type);
803 if (map_value_has_timer(map)) {
804 if (map->map_flags & BPF_F_RDONLY_PROG)
805 return -EACCES;
806 if (map->map_type != BPF_MAP_TYPE_HASH &&
807 map->map_type != BPF_MAP_TYPE_LRU_HASH &&
808 map->map_type != BPF_MAP_TYPE_ARRAY)
809 return -EOPNOTSUPP;
810 }
811
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200812 if (map->ops->map_check_btf)
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800813 ret = map->ops->map_check_btf(map, btf, key_type, value_type);
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200814
815 return ret;
816}
817
Joanne Koong93309862021-10-27 16:45:00 -0700818#define BPF_MAP_CREATE_LAST_FIELD map_extra
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700819/* called via syscall */
820static int map_create(union bpf_attr *attr)
821{
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700822 int numa_node = bpf_map_attr_numa_node(attr);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700823 struct bpf_map *map;
Chenbo Feng6e71b042017-10-18 13:00:22 -0700824 int f_flags;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700825 int err;
826
827 err = CHECK_ATTR(BPF_MAP_CREATE);
828 if (err)
829 return -EINVAL;
830
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800831 if (attr->btf_vmlinux_value_type_id) {
832 if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS ||
833 attr->btf_key_type_id || attr->btf_value_type_id)
834 return -EINVAL;
835 } else if (attr->btf_key_type_id && !attr->btf_value_type_id) {
836 return -EINVAL;
837 }
838
Joanne Koong93309862021-10-27 16:45:00 -0700839 if (attr->map_type != BPF_MAP_TYPE_BLOOM_FILTER &&
840 attr->map_extra != 0)
841 return -EINVAL;
842
Chenbo Feng6e71b042017-10-18 13:00:22 -0700843 f_flags = bpf_get_file_flag(attr->map_flags);
844 if (f_flags < 0)
845 return f_flags;
846
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700847 if (numa_node != NUMA_NO_NODE &&
Eric Dumazet96e5ae42017-09-04 22:41:02 -0700848 ((unsigned int)numa_node >= nr_node_ids ||
849 !node_online(numa_node)))
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700850 return -EINVAL;
851
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700852 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
853 map = find_and_alloc_map(attr);
854 if (IS_ERR(map))
855 return PTR_ERR(map);
856
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700857 err = bpf_obj_name_cpy(map->name, attr->map_name,
858 sizeof(attr->map_name));
859 if (err < 0)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700860 goto free_map;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -0700861
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800862 atomic64_set(&map->refcnt, 1);
863 atomic64_set(&map->usercnt, 1);
Andrii Nakryikofc970222019-11-17 09:28:04 -0800864 mutex_init(&map->freeze_mutex);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700865
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800866 map->spin_lock_off = -EINVAL;
Alexei Starovoitov68134662021-07-14 17:54:10 -0700867 map->timer_off = -EINVAL;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800868 if (attr->btf_key_type_id || attr->btf_value_type_id ||
869 /* Even the map's value is a kernel's struct,
870 * the bpf_prog.o must have BTF to begin with
871 * to figure out the corresponding kernel's
872 * counter part. Thus, attr->btf_fd has
873 * to be valid also.
874 */
875 attr->btf_vmlinux_value_type_id) {
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700876 struct btf *btf;
877
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700878 btf = btf_get_by_fd(attr->btf_fd);
879 if (IS_ERR(btf)) {
880 err = PTR_ERR(btf);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700881 goto free_map;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700882 }
Alexei Starovoitov350a5c42021-03-07 14:52:48 -0800883 if (btf_is_kernel(btf)) {
884 btf_put(btf);
885 err = -EACCES;
886 goto free_map;
887 }
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800888 map->btf = btf;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700889
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800890 if (attr->btf_value_type_id) {
891 err = map_check_btf(map, btf, attr->btf_key_type_id,
892 attr->btf_value_type_id);
893 if (err)
894 goto free_map;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700895 }
896
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -0700897 map->btf_key_type_id = attr->btf_key_type_id;
898 map->btf_value_type_id = attr->btf_value_type_id;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800899 map->btf_vmlinux_value_type_id =
900 attr->btf_vmlinux_value_type_id;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700901 }
902
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700903 err = security_bpf_map_alloc(map);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700904 if (err)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700905 goto free_map;
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700906
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700907 err = bpf_map_alloc_id(map);
908 if (err)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700909 goto free_map_sec;
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700910
Roman Gushchin48edc1f2020-12-01 13:58:32 -0800911 bpf_map_save_memcg(map);
912
Chenbo Feng6e71b042017-10-18 13:00:22 -0700913 err = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700914 if (err < 0) {
915 /* failed to allocate fd.
Peng Sun352d20d2019-02-27 22:36:25 +0800916 * bpf_map_put_with_uref() is needed because the above
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700917 * bpf_map_alloc_id() has published the map
918 * to the userspace and the userspace may
919 * have refcnt-ed it through BPF_MAP_GET_FD_BY_ID.
920 */
Peng Sun352d20d2019-02-27 22:36:25 +0800921 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700922 return err;
923 }
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700924
925 return err;
926
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700927free_map_sec:
928 security_bpf_map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700929free_map:
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700930 btf_put(map->btf);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700931 map->ops->map_free(map);
932 return err;
933}
934
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700935/* if error is returned, fd is released.
936 * On success caller should complete fd access with matching fdput()
937 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100938struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700939{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700940 if (!f.file)
941 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700942 if (f.file->f_op != &bpf_map_fops) {
943 fdput(f);
944 return ERR_PTR(-EINVAL);
945 }
946
Daniel Borkmannc2101292015-10-29 14:58:07 +0100947 return f.file->private_data;
948}
949
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800950void bpf_map_inc(struct bpf_map *map)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100951{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800952 atomic64_inc(&map->refcnt);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100953}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700954EXPORT_SYMBOL_GPL(bpf_map_inc);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100955
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800956void bpf_map_inc_with_uref(struct bpf_map *map)
957{
958 atomic64_inc(&map->refcnt);
959 atomic64_inc(&map->usercnt);
960}
961EXPORT_SYMBOL_GPL(bpf_map_inc_with_uref);
962
Martin KaFai Lau1ed4d922020-02-25 15:04:21 -0800963struct bpf_map *bpf_map_get(u32 ufd)
964{
965 struct fd f = fdget(ufd);
966 struct bpf_map *map;
967
968 map = __bpf_map_get(f);
969 if (IS_ERR(map))
970 return map;
971
972 bpf_map_inc(map);
973 fdput(f);
974
975 return map;
976}
977
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100978struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +0100979{
980 struct fd f = fdget(ufd);
981 struct bpf_map *map;
982
983 map = __bpf_map_get(f);
984 if (IS_ERR(map))
985 return map;
986
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800987 bpf_map_inc_with_uref(map);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100988 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700989
990 return map;
991}
992
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700993/* map_idr_lock should have been held */
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800994static struct bpf_map *__bpf_map_inc_not_zero(struct bpf_map *map, bool uref)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700995{
996 int refold;
997
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800998 refold = atomic64_fetch_add_unless(&map->refcnt, 1, 0);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700999 if (!refold)
1000 return ERR_PTR(-ENOENT);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001001 if (uref)
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001002 atomic64_inc(&map->usercnt);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001003
1004 return map;
1005}
1006
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001007struct bpf_map *bpf_map_inc_not_zero(struct bpf_map *map)
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07001008{
1009 spin_lock_bh(&map_idr_lock);
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001010 map = __bpf_map_inc_not_zero(map, false);
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07001011 spin_unlock_bh(&map_idr_lock);
1012
1013 return map;
1014}
1015EXPORT_SYMBOL_GPL(bpf_map_inc_not_zero);
1016
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -08001017int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
1018{
1019 return -ENOTSUPP;
1020}
1021
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001022static void *__bpf_copy_key(void __user *ukey, u64 key_size)
1023{
1024 if (key_size)
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001025 return vmemdup_user(ukey, key_size);
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001026
1027 if (ukey)
1028 return ERR_PTR(-EINVAL);
1029
1030 return NULL;
1031}
1032
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07001033static void *___bpf_copy_key(bpfptr_t ukey, u64 key_size)
1034{
1035 if (key_size)
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001036 return kvmemdup_bpfptr(ukey, key_size);
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07001037
1038 if (!bpfptr_is_null(ukey))
1039 return ERR_PTR(-EINVAL);
1040
1041 return NULL;
1042}
1043
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001044/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001045#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001046
1047static int map_lookup_elem(union bpf_attr *attr)
1048{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001049 void __user *ukey = u64_to_user_ptr(attr->key);
1050 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001051 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001052 struct bpf_map *map;
Brian Vazquez15c14a32020-01-15 10:43:00 -08001053 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001054 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001055 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001056 int err;
1057
1058 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
1059 return -EINVAL;
1060
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001061 if (attr->flags & ~BPF_F_LOCK)
1062 return -EINVAL;
1063
Daniel Borkmann592867b2015-09-08 18:00:09 +02001064 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001065 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001066 if (IS_ERR(map))
1067 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001068 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001069 err = -EPERM;
1070 goto err_put;
1071 }
1072
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001073 if ((attr->flags & BPF_F_LOCK) &&
1074 !map_value_has_spin_lock(map)) {
1075 err = -EINVAL;
1076 goto err_put;
1077 }
1078
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001079 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001080 if (IS_ERR(key)) {
1081 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001082 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001083 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001084
Brian Vazquez15c14a32020-01-15 10:43:00 -08001085 value_size = bpf_map_value_size(map);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001086
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001087 err = -ENOMEM;
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001088 value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001089 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001090 goto free_key;
1091
Joanne Koong93309862021-10-27 16:45:00 -07001092 if (map->map_type == BPF_MAP_TYPE_BLOOM_FILTER) {
1093 if (copy_from_user(value, uvalue, value_size))
1094 err = -EFAULT;
1095 else
1096 err = bpf_map_copy_value(map, key, value, attr->flags);
1097 goto free_value;
1098 }
1099
Brian Vazquez15c14a32020-01-15 10:43:00 -08001100 err = bpf_map_copy_value(map, key, value, attr->flags);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001101 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001102 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001103
1104 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001105 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001106 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001107
1108 err = 0;
1109
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001110free_value:
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001111 kvfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001112free_key:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001113 kvfree(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001114err_put:
1115 fdput(f);
1116 return err;
1117}
1118
Daniel Colascione1ae80cf2018-10-12 03:54:27 -07001119
Alexei Starovoitov3274f522014-11-13 17:36:44 -08001120#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001121
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07001122static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001123{
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07001124 bpfptr_t ukey = make_bpfptr(attr->key, uattr.is_kernel);
1125 bpfptr_t uvalue = make_bpfptr(attr->value, uattr.is_kernel);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001126 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001127 struct bpf_map *map;
1128 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001129 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001130 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001131 int err;
1132
1133 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
1134 return -EINVAL;
1135
Daniel Borkmann592867b2015-09-08 18:00:09 +02001136 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001137 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001138 if (IS_ERR(map))
1139 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001140 if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001141 err = -EPERM;
1142 goto err_put;
1143 }
1144
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001145 if ((attr->flags & BPF_F_LOCK) &&
1146 !map_value_has_spin_lock(map)) {
1147 err = -EINVAL;
1148 goto err_put;
1149 }
1150
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07001151 key = ___bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001152 if (IS_ERR(key)) {
1153 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001154 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001155 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001156
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001157 value_size = bpf_map_value_size(map);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001158
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001159 err = -ENOMEM;
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001160 value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001161 if (!value)
1162 goto free_key;
1163
1164 err = -EFAULT;
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07001165 if (copy_from_bpfptr(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001166 goto free_value;
1167
Brian Vazquez15c14a32020-01-15 10:43:00 -08001168 err = bpf_map_update_value(map, f, key, value, attr->flags);
Jesper Dangaard Brouer6710e112017-10-16 12:19:28 +02001169
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001170free_value:
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001171 kvfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001172free_key:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001173 kvfree(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001174err_put:
1175 fdput(f);
1176 return err;
1177}
1178
1179#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
1180
1181static int map_delete_elem(union bpf_attr *attr)
1182{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001183 void __user *ukey = u64_to_user_ptr(attr->key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001184 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001185 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001186 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001187 void *key;
1188 int err;
1189
1190 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
1191 return -EINVAL;
1192
Daniel Borkmann592867b2015-09-08 18:00:09 +02001193 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001194 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001195 if (IS_ERR(map))
1196 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001197 if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001198 err = -EPERM;
1199 goto err_put;
1200 }
1201
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001202 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001203 if (IS_ERR(key)) {
1204 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001205 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001206 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001207
Jakub Kicinskia3884572018-01-11 20:29:09 -08001208 if (bpf_map_is_dev_bound(map)) {
1209 err = bpf_map_offload_delete_elem(map, key);
1210 goto out;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -08001211 } else if (IS_FD_PROG_ARRAY(map) ||
1212 map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
1213 /* These maps require sleepable context */
Daniel Borkmannda765a22019-11-22 21:07:58 +01001214 err = map->ops->map_delete_elem(map, key);
1215 goto out;
Jakub Kicinskia3884572018-01-11 20:29:09 -08001216 }
1217
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001218 bpf_disable_instrumentation();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001219 rcu_read_lock();
1220 err = map->ops->map_delete_elem(map, key);
1221 rcu_read_unlock();
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001222 bpf_enable_instrumentation();
Daniel Colascione1ae80cf2018-10-12 03:54:27 -07001223 maybe_wait_bpf_programs(map);
Jakub Kicinskia3884572018-01-11 20:29:09 -08001224out:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001225 kvfree(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001226err_put:
1227 fdput(f);
1228 return err;
1229}
1230
1231/* last field in 'union bpf_attr' used by this command */
1232#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
1233
1234static int map_get_next_key(union bpf_attr *attr)
1235{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001236 void __user *ukey = u64_to_user_ptr(attr->key);
1237 void __user *unext_key = u64_to_user_ptr(attr->next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001238 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001239 struct bpf_map *map;
1240 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001241 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001242 int err;
1243
1244 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
1245 return -EINVAL;
1246
Daniel Borkmann592867b2015-09-08 18:00:09 +02001247 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001248 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001249 if (IS_ERR(map))
1250 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001251 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001252 err = -EPERM;
1253 goto err_put;
1254 }
1255
Teng Qin8fe45922017-04-24 19:00:37 -07001256 if (ukey) {
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001257 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001258 if (IS_ERR(key)) {
1259 err = PTR_ERR(key);
Teng Qin8fe45922017-04-24 19:00:37 -07001260 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001261 }
Teng Qin8fe45922017-04-24 19:00:37 -07001262 } else {
1263 key = NULL;
1264 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001265
1266 err = -ENOMEM;
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001267 next_key = kvmalloc(map->key_size, GFP_USER);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001268 if (!next_key)
1269 goto free_key;
1270
Jakub Kicinskia3884572018-01-11 20:29:09 -08001271 if (bpf_map_is_dev_bound(map)) {
1272 err = bpf_map_offload_get_next_key(map, key, next_key);
1273 goto out;
1274 }
1275
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001276 rcu_read_lock();
1277 err = map->ops->map_get_next_key(map, key, next_key);
1278 rcu_read_unlock();
Jakub Kicinskia3884572018-01-11 20:29:09 -08001279out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001280 if (err)
1281 goto free_next_key;
1282
1283 err = -EFAULT;
1284 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
1285 goto free_next_key;
1286
1287 err = 0;
1288
1289free_next_key:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001290 kvfree(next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001291free_key:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001292 kvfree(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001293err_put:
1294 fdput(f);
1295 return err;
1296}
1297
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001298int generic_map_delete_batch(struct bpf_map *map,
1299 const union bpf_attr *attr,
1300 union bpf_attr __user *uattr)
1301{
1302 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1303 u32 cp, max_count;
1304 int err = 0;
1305 void *key;
1306
1307 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1308 return -EINVAL;
1309
1310 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1311 !map_value_has_spin_lock(map)) {
1312 return -EINVAL;
1313 }
1314
1315 max_count = attr->batch.count;
1316 if (!max_count)
1317 return 0;
1318
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001319 key = kvmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001320 if (!key)
1321 return -ENOMEM;
1322
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001323 for (cp = 0; cp < max_count; cp++) {
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001324 err = -EFAULT;
1325 if (copy_from_user(key, keys + cp * map->key_size,
1326 map->key_size))
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001327 break;
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001328
1329 if (bpf_map_is_dev_bound(map)) {
1330 err = bpf_map_offload_delete_elem(map, key);
1331 break;
1332 }
1333
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001334 bpf_disable_instrumentation();
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001335 rcu_read_lock();
1336 err = map->ops->map_delete_elem(map, key);
1337 rcu_read_unlock();
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001338 bpf_enable_instrumentation();
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001339 maybe_wait_bpf_programs(map);
1340 if (err)
1341 break;
1342 }
1343 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
1344 err = -EFAULT;
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001345
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001346 kvfree(key);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001347 return err;
1348}
1349
1350int generic_map_update_batch(struct bpf_map *map,
1351 const union bpf_attr *attr,
1352 union bpf_attr __user *uattr)
1353{
1354 void __user *values = u64_to_user_ptr(attr->batch.values);
1355 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1356 u32 value_size, cp, max_count;
1357 int ufd = attr->map_fd;
1358 void *key, *value;
1359 struct fd f;
1360 int err = 0;
1361
1362 f = fdget(ufd);
1363 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1364 return -EINVAL;
1365
1366 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1367 !map_value_has_spin_lock(map)) {
1368 return -EINVAL;
1369 }
1370
1371 value_size = bpf_map_value_size(map);
1372
1373 max_count = attr->batch.count;
1374 if (!max_count)
1375 return 0;
1376
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001377 key = kvmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001378 if (!key)
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001379 return -ENOMEM;
1380
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001381 value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001382 if (!value) {
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001383 kvfree(key);
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001384 return -ENOMEM;
1385 }
1386
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001387 for (cp = 0; cp < max_count; cp++) {
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001388 err = -EFAULT;
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001389 if (copy_from_user(key, keys + cp * map->key_size,
1390 map->key_size) ||
1391 copy_from_user(value, values + cp * value_size, value_size))
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001392 break;
1393
1394 err = bpf_map_update_value(map, f, key, value,
1395 attr->batch.elem_flags);
1396
1397 if (err)
1398 break;
1399 }
1400
1401 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
1402 err = -EFAULT;
1403
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001404 kvfree(value);
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001405 kvfree(key);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001406 return err;
1407}
1408
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001409#define MAP_LOOKUP_RETRIES 3
1410
1411int generic_map_lookup_batch(struct bpf_map *map,
1412 const union bpf_attr *attr,
1413 union bpf_attr __user *uattr)
1414{
1415 void __user *uobatch = u64_to_user_ptr(attr->batch.out_batch);
1416 void __user *ubatch = u64_to_user_ptr(attr->batch.in_batch);
1417 void __user *values = u64_to_user_ptr(attr->batch.values);
1418 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1419 void *buf, *buf_prevkey, *prev_key, *key, *value;
1420 int err, retry = MAP_LOOKUP_RETRIES;
1421 u32 value_size, cp, max_count;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001422
1423 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1424 return -EINVAL;
1425
1426 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1427 !map_value_has_spin_lock(map))
1428 return -EINVAL;
1429
1430 value_size = bpf_map_value_size(map);
1431
1432 max_count = attr->batch.count;
1433 if (!max_count)
1434 return 0;
1435
1436 if (put_user(0, &uattr->batch.count))
1437 return -EFAULT;
1438
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001439 buf_prevkey = kvmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001440 if (!buf_prevkey)
1441 return -ENOMEM;
1442
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001443 buf = kvmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001444 if (!buf) {
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001445 kvfree(buf_prevkey);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001446 return -ENOMEM;
1447 }
1448
1449 err = -EFAULT;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001450 prev_key = NULL;
1451 if (ubatch && copy_from_user(buf_prevkey, ubatch, map->key_size))
1452 goto free_buf;
1453 key = buf;
1454 value = key + map->key_size;
1455 if (ubatch)
1456 prev_key = buf_prevkey;
1457
1458 for (cp = 0; cp < max_count;) {
1459 rcu_read_lock();
1460 err = map->ops->map_get_next_key(map, prev_key, key);
1461 rcu_read_unlock();
1462 if (err)
1463 break;
1464 err = bpf_map_copy_value(map, key, value,
1465 attr->batch.elem_flags);
1466
1467 if (err == -ENOENT) {
1468 if (retry) {
1469 retry--;
1470 continue;
1471 }
1472 err = -EINTR;
1473 break;
1474 }
1475
1476 if (err)
1477 goto free_buf;
1478
1479 if (copy_to_user(keys + cp * map->key_size, key,
1480 map->key_size)) {
1481 err = -EFAULT;
1482 goto free_buf;
1483 }
1484 if (copy_to_user(values + cp * value_size, value, value_size)) {
1485 err = -EFAULT;
1486 goto free_buf;
1487 }
1488
1489 if (!prev_key)
1490 prev_key = buf_prevkey;
1491
1492 swap(prev_key, key);
1493 retry = MAP_LOOKUP_RETRIES;
1494 cp++;
1495 }
1496
1497 if (err == -EFAULT)
1498 goto free_buf;
1499
1500 if ((copy_to_user(&uattr->batch.count, &cp, sizeof(cp)) ||
1501 (cp && copy_to_user(uobatch, prev_key, map->key_size))))
1502 err = -EFAULT;
1503
1504free_buf:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001505 kvfree(buf_prevkey);
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001506 kvfree(buf);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001507 return err;
1508}
1509
Denis Salopek3e87f192021-05-11 23:00:04 +02001510#define BPF_MAP_LOOKUP_AND_DELETE_ELEM_LAST_FIELD flags
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001511
1512static int map_lookup_and_delete_elem(union bpf_attr *attr)
1513{
1514 void __user *ukey = u64_to_user_ptr(attr->key);
1515 void __user *uvalue = u64_to_user_ptr(attr->value);
1516 int ufd = attr->map_fd;
1517 struct bpf_map *map;
Alexei Starovoitov540fefc2018-10-19 13:52:38 -07001518 void *key, *value;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001519 u32 value_size;
1520 struct fd f;
1521 int err;
1522
1523 if (CHECK_ATTR(BPF_MAP_LOOKUP_AND_DELETE_ELEM))
1524 return -EINVAL;
1525
Denis Salopek3e87f192021-05-11 23:00:04 +02001526 if (attr->flags & ~BPF_F_LOCK)
1527 return -EINVAL;
1528
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001529 f = fdget(ufd);
1530 map = __bpf_map_get(f);
1531 if (IS_ERR(map))
1532 return PTR_ERR(map);
Anton Protopopov1ea0f912020-05-27 18:56:59 +00001533 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) ||
1534 !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001535 err = -EPERM;
1536 goto err_put;
1537 }
1538
Denis Salopek3e87f192021-05-11 23:00:04 +02001539 if (attr->flags &&
1540 (map->map_type == BPF_MAP_TYPE_QUEUE ||
1541 map->map_type == BPF_MAP_TYPE_STACK)) {
1542 err = -EINVAL;
1543 goto err_put;
1544 }
1545
1546 if ((attr->flags & BPF_F_LOCK) &&
1547 !map_value_has_spin_lock(map)) {
1548 err = -EINVAL;
1549 goto err_put;
1550 }
1551
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001552 key = __bpf_copy_key(ukey, map->key_size);
1553 if (IS_ERR(key)) {
1554 err = PTR_ERR(key);
1555 goto err_put;
1556 }
1557
Denis Salopek3e87f192021-05-11 23:00:04 +02001558 value_size = bpf_map_value_size(map);
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001559
1560 err = -ENOMEM;
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001561 value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001562 if (!value)
1563 goto free_key;
1564
Denis Salopek3e87f192021-05-11 23:00:04 +02001565 err = -ENOTSUPP;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001566 if (map->map_type == BPF_MAP_TYPE_QUEUE ||
1567 map->map_type == BPF_MAP_TYPE_STACK) {
1568 err = map->ops->map_pop_elem(map, value);
Denis Salopek3e87f192021-05-11 23:00:04 +02001569 } else if (map->map_type == BPF_MAP_TYPE_HASH ||
1570 map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
1571 map->map_type == BPF_MAP_TYPE_LRU_HASH ||
1572 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
1573 if (!bpf_map_is_dev_bound(map)) {
1574 bpf_disable_instrumentation();
1575 rcu_read_lock();
1576 err = map->ops->map_lookup_and_delete_elem(map, key, value, attr->flags);
1577 rcu_read_unlock();
1578 bpf_enable_instrumentation();
1579 }
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001580 }
1581
1582 if (err)
1583 goto free_value;
1584
Wei Yongjun7f645462020-04-30 08:18:51 +00001585 if (copy_to_user(uvalue, value, value_size) != 0) {
1586 err = -EFAULT;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001587 goto free_value;
Wei Yongjun7f645462020-04-30 08:18:51 +00001588 }
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001589
1590 err = 0;
1591
1592free_value:
Stanislav Fomichevf0dce1d2021-08-18 16:52:15 -07001593 kvfree(value);
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001594free_key:
Stanislav Fomichev44779a4b2021-08-18 16:52:16 -07001595 kvfree(key);
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001596err_put:
1597 fdput(f);
1598 return err;
1599}
1600
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001601#define BPF_MAP_FREEZE_LAST_FIELD map_fd
1602
1603static int map_freeze(const union bpf_attr *attr)
1604{
1605 int err = 0, ufd = attr->map_fd;
1606 struct bpf_map *map;
1607 struct fd f;
1608
1609 if (CHECK_ATTR(BPF_MAP_FREEZE))
1610 return -EINVAL;
1611
1612 f = fdget(ufd);
1613 map = __bpf_map_get(f);
1614 if (IS_ERR(map))
1615 return PTR_ERR(map);
Andrii Nakryikofc970222019-11-17 09:28:04 -08001616
Alexei Starovoitov68134662021-07-14 17:54:10 -07001617 if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS ||
1618 map_value_has_timer(map)) {
Martin KaFai Lau849b4d92020-03-04 17:34:54 -08001619 fdput(f);
1620 return -ENOTSUPP;
1621 }
1622
Andrii Nakryikofc970222019-11-17 09:28:04 -08001623 mutex_lock(&map->freeze_mutex);
1624
1625 if (map->writecnt) {
1626 err = -EBUSY;
1627 goto err_put;
1628 }
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001629 if (READ_ONCE(map->frozen)) {
1630 err = -EBUSY;
1631 goto err_put;
1632 }
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07001633 if (!bpf_capable()) {
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001634 err = -EPERM;
1635 goto err_put;
1636 }
1637
1638 WRITE_ONCE(map->frozen, true);
1639err_put:
Andrii Nakryikofc970222019-11-17 09:28:04 -08001640 mutex_unlock(&map->freeze_mutex);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001641 fdput(f);
1642 return err;
1643}
1644
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001645static const struct bpf_prog_ops * const bpf_prog_types[] = {
Alexei Starovoitov91cc1a92019-11-14 10:57:15 -08001646#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001647 [_id] = & _name ## _prog_ops,
1648#define BPF_MAP_TYPE(_id, _ops)
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07001649#define BPF_LINK_TYPE(_id, _name)
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001650#include <linux/bpf_types.h>
1651#undef BPF_PROG_TYPE
1652#undef BPF_MAP_TYPE
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07001653#undef BPF_LINK_TYPE
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001654};
1655
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001656static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
1657{
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001658 const struct bpf_prog_ops *ops;
1659
1660 if (type >= ARRAY_SIZE(bpf_prog_types))
1661 return -EINVAL;
1662 type = array_index_nospec(type, ARRAY_SIZE(bpf_prog_types));
1663 ops = bpf_prog_types[type];
1664 if (!ops)
Johannes Bergbe9370a2017-04-11 15:34:57 +02001665 return -EINVAL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001666
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001667 if (!bpf_prog_is_dev_bound(prog->aux))
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001668 prog->aux->ops = ops;
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001669 else
1670 prog->aux->ops = &bpf_offload_prog_ops;
Johannes Bergbe9370a2017-04-11 15:34:57 +02001671 prog->type = type;
1672 return 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001673}
1674
Daniel Borkmannbae141f2019-12-06 22:49:34 +01001675enum bpf_audit {
1676 BPF_AUDIT_LOAD,
1677 BPF_AUDIT_UNLOAD,
1678 BPF_AUDIT_MAX,
1679};
1680
1681static const char * const bpf_audit_str[BPF_AUDIT_MAX] = {
1682 [BPF_AUDIT_LOAD] = "LOAD",
1683 [BPF_AUDIT_UNLOAD] = "UNLOAD",
1684};
1685
1686static void bpf_audit_prog(const struct bpf_prog *prog, unsigned int op)
1687{
1688 struct audit_context *ctx = NULL;
1689 struct audit_buffer *ab;
1690
1691 if (WARN_ON_ONCE(op >= BPF_AUDIT_MAX))
1692 return;
1693 if (audit_enabled == AUDIT_OFF)
1694 return;
1695 if (op == BPF_AUDIT_LOAD)
1696 ctx = audit_context();
1697 ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_BPF);
1698 if (unlikely(!ab))
1699 return;
1700 audit_log_format(ab, "prog-id=%u op=%s",
1701 prog->aux->id, bpf_audit_str[op]);
1702 audit_log_end(ab);
1703}
1704
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001705static int bpf_prog_alloc_id(struct bpf_prog *prog)
1706{
1707 int id;
1708
Shaohua Lib76354c2018-03-27 11:53:21 -07001709 idr_preload(GFP_KERNEL);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001710 spin_lock_bh(&prog_idr_lock);
1711 id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
1712 if (id > 0)
1713 prog->aux->id = id;
1714 spin_unlock_bh(&prog_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -07001715 idr_preload_end();
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001716
1717 /* id is in [1, INT_MAX) */
1718 if (WARN_ON_ONCE(!id))
1719 return -ENOSPC;
1720
1721 return id > 0 ? 0 : id;
1722}
1723
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001724void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001725{
Alexei Starovoitovd809e132021-07-14 17:54:07 -07001726 unsigned long flags;
1727
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001728 /* cBPF to eBPF migrations are currently not in the idr store.
1729 * Offloaded programs are removed from the store when their device
1730 * disappears - even if someone grabs an fd to them they are unusable,
1731 * simply waiting for refcnt to drop to be freed.
1732 */
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001733 if (!prog->aux->id)
1734 return;
1735
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001736 if (do_idr_lock)
Alexei Starovoitovd809e132021-07-14 17:54:07 -07001737 spin_lock_irqsave(&prog_idr_lock, flags);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001738 else
1739 __acquire(&prog_idr_lock);
1740
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001741 idr_remove(&prog_idr, prog->aux->id);
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001742 prog->aux->id = 0;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001743
1744 if (do_idr_lock)
Alexei Starovoitovd809e132021-07-14 17:54:07 -07001745 spin_unlock_irqrestore(&prog_idr_lock, flags);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001746 else
1747 __release(&prog_idr_lock);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001748}
1749
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001750static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001751{
1752 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
1753
Daniel Borkmann3b4d9eb2019-10-22 23:30:38 +02001754 kvfree(aux->func_info);
Alexei Starovoitov8c1b6e62019-11-14 10:57:16 -08001755 kfree(aux->func_info_aux);
Roman Gushchin3ac1f012020-12-01 13:58:59 -08001756 free_uid(aux->user);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001757 security_bpf_prog_free(aux);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001758 bpf_prog_free(aux->prog);
1759}
1760
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001761static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred)
1762{
1763 bpf_prog_kallsyms_del_all(prog);
1764 btf_put(prog->aux->btf);
Martin KaFai Laue16301f2021-03-24 18:51:30 -07001765 kvfree(prog->aux->jited_linfo);
1766 kvfree(prog->aux->linfo);
Martin KaFai Laue6ac2452021-03-24 18:51:42 -07001767 kfree(prog->aux->kfunc_tab);
Andrii Nakryiko22dc4a02020-12-03 12:46:29 -08001768 if (prog->aux->attach_btf)
1769 btf_put(prog->aux->attach_btf);
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001770
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07001771 if (deferred) {
1772 if (prog->aux->sleepable)
1773 call_rcu_tasks_trace(&prog->aux->rcu, __bpf_prog_put_rcu);
1774 else
1775 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1776 } else {
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001777 __bpf_prog_put_rcu(&prog->aux->rcu);
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07001778 }
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001779}
1780
Alexei Starovoitovd809e132021-07-14 17:54:07 -07001781static void bpf_prog_put_deferred(struct work_struct *work)
1782{
1783 struct bpf_prog_aux *aux;
1784 struct bpf_prog *prog;
1785
1786 aux = container_of(work, struct bpf_prog_aux, work);
1787 prog = aux->prog;
1788 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
1789 bpf_audit_prog(prog, BPF_AUDIT_UNLOAD);
1790 __bpf_prog_put_noref(prog, true);
1791}
1792
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001793static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001794{
Alexei Starovoitovd809e132021-07-14 17:54:07 -07001795 struct bpf_prog_aux *aux = prog->aux;
1796
1797 if (atomic64_dec_and_test(&aux->refcnt)) {
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001798 /* bpf_prog_free_id() must be called first */
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001799 bpf_prog_free_id(prog, do_idr_lock);
Alexei Starovoitovd809e132021-07-14 17:54:07 -07001800
1801 if (in_irq() || irqs_disabled()) {
1802 INIT_WORK(&aux->work, bpf_prog_put_deferred);
1803 schedule_work(&aux->work);
1804 } else {
1805 bpf_prog_put_deferred(&aux->work);
1806 }
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01001807 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001808}
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001809
1810void bpf_prog_put(struct bpf_prog *prog)
1811{
1812 __bpf_prog_put(prog, true);
1813}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +01001814EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001815
1816static int bpf_prog_release(struct inode *inode, struct file *filp)
1817{
1818 struct bpf_prog *prog = filp->private_data;
1819
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001820 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001821 return 0;
1822}
1823
Eric Dumazet61a0aba2021-10-26 14:41:33 -07001824struct bpf_prog_kstats {
1825 u64 nsecs;
1826 u64 cnt;
1827 u64 misses;
1828};
1829
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001830static void bpf_prog_get_stats(const struct bpf_prog *prog,
Eric Dumazet61a0aba2021-10-26 14:41:33 -07001831 struct bpf_prog_kstats *stats)
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001832{
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08001833 u64 nsecs = 0, cnt = 0, misses = 0;
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001834 int cpu;
1835
1836 for_each_possible_cpu(cpu) {
1837 const struct bpf_prog_stats *st;
1838 unsigned int start;
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08001839 u64 tnsecs, tcnt, tmisses;
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001840
Alexei Starovoitov700d4792021-02-09 19:36:26 -08001841 st = per_cpu_ptr(prog->stats, cpu);
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001842 do {
1843 start = u64_stats_fetch_begin_irq(&st->syncp);
Eric Dumazet61a0aba2021-10-26 14:41:33 -07001844 tnsecs = u64_stats_read(&st->nsecs);
1845 tcnt = u64_stats_read(&st->cnt);
1846 tmisses = u64_stats_read(&st->misses);
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001847 } while (u64_stats_fetch_retry_irq(&st->syncp, start));
1848 nsecs += tnsecs;
1849 cnt += tcnt;
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08001850 misses += tmisses;
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001851 }
1852 stats->nsecs = nsecs;
1853 stats->cnt = cnt;
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08001854 stats->misses = misses;
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001855}
1856
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001857#ifdef CONFIG_PROC_FS
1858static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
1859{
1860 const struct bpf_prog *prog = filp->private_data;
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001861 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Eric Dumazet61a0aba2021-10-26 14:41:33 -07001862 struct bpf_prog_kstats stats;
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001863
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001864 bpf_prog_get_stats(prog, &stats);
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001865 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001866 seq_printf(m,
1867 "prog_type:\t%u\n"
1868 "prog_jited:\t%u\n"
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001869 "prog_tag:\t%s\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +02001870 "memlock:\t%llu\n"
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001871 "prog_id:\t%u\n"
1872 "run_time_ns:\t%llu\n"
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08001873 "run_cnt:\t%llu\n"
Dave Marchevskyaba64c72021-10-20 00:48:17 -07001874 "recursion_misses:\t%llu\n"
1875 "verified_insns:\t%u\n",
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001876 prog->type,
1877 prog->jited,
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001878 prog_tag,
Daniel Borkmann4316b402018-06-02 23:06:34 +02001879 prog->pages * 1ULL << PAGE_SHIFT,
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001880 prog->aux->id,
1881 stats.nsecs,
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08001882 stats.cnt,
Dave Marchevskyaba64c72021-10-20 00:48:17 -07001883 stats.misses,
1884 prog->aux->verified_insns);
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001885}
1886#endif
1887
Chenbo Fengf66e4482017-10-18 13:00:26 -07001888const struct file_operations bpf_prog_fops = {
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001889#ifdef CONFIG_PROC_FS
1890 .show_fdinfo = bpf_prog_show_fdinfo,
1891#endif
1892 .release = bpf_prog_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -07001893 .read = bpf_dummy_read,
1894 .write = bpf_dummy_write,
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001895};
1896
Daniel Borkmannb2197752015-10-29 14:58:09 +01001897int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +01001898{
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001899 int ret;
1900
1901 ret = security_bpf_prog(prog);
1902 if (ret < 0)
1903 return ret;
1904
Daniel Borkmannaa797812015-10-29 14:58:06 +01001905 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
1906 O_RDWR | O_CLOEXEC);
1907}
1908
Daniel Borkmann113214b2016-06-30 17:24:44 +02001909static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001910{
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001911 if (!f.file)
1912 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001913 if (f.file->f_op != &bpf_prog_fops) {
1914 fdput(f);
1915 return ERR_PTR(-EINVAL);
1916 }
1917
Daniel Borkmannc2101292015-10-29 14:58:07 +01001918 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001919}
1920
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001921void bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001922{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001923 atomic64_add(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001924}
Brenden Blanco59d36562016-07-19 12:16:46 -07001925EXPORT_SYMBOL_GPL(bpf_prog_add);
1926
Daniel Borkmannc5405942016-11-09 22:02:34 +01001927void bpf_prog_sub(struct bpf_prog *prog, int i)
1928{
1929 /* Only to be used for undoing previous bpf_prog_add() in some
1930 * error path. We still know that another entity in our call
1931 * path holds a reference to the program, thus atomic_sub() can
1932 * be safely used in such cases!
1933 */
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001934 WARN_ON(atomic64_sub_return(i, &prog->aux->refcnt) == 0);
Daniel Borkmannc5405942016-11-09 22:02:34 +01001935}
1936EXPORT_SYMBOL_GPL(bpf_prog_sub);
1937
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001938void bpf_prog_inc(struct bpf_prog *prog)
Brenden Blanco59d36562016-07-19 12:16:46 -07001939{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001940 atomic64_inc(&prog->aux->refcnt);
Brenden Blanco59d36562016-07-19 12:16:46 -07001941}
Daniel Borkmann97bc4022016-11-19 01:45:00 +01001942EXPORT_SYMBOL_GPL(bpf_prog_inc);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001943
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001944/* prog_idr_lock should have been held */
John Fastabenda6f6df62017-08-15 22:32:22 -07001945struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001946{
1947 int refold;
1948
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001949 refold = atomic64_fetch_add_unless(&prog->aux->refcnt, 1, 0);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001950
1951 if (!refold)
1952 return ERR_PTR(-ENOENT);
1953
1954 return prog;
1955}
John Fastabenda6f6df62017-08-15 22:32:22 -07001956EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001957
Al Viro040ee692017-12-02 20:20:38 -05001958bool bpf_prog_get_ok(struct bpf_prog *prog,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001959 enum bpf_prog_type *attach_type, bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001960{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001961 /* not an attachment, just a refcount inc, always allow */
1962 if (!attach_type)
1963 return true;
Jakub Kicinski248f3462017-11-03 13:56:20 -07001964
1965 if (prog->type != *attach_type)
1966 return false;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001967 if (bpf_prog_is_dev_bound(prog->aux) && !attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001968 return false;
1969
1970 return true;
1971}
1972
1973static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001974 bool attach_drv)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001975{
1976 struct fd f = fdget(ufd);
1977 struct bpf_prog *prog;
1978
Daniel Borkmann113214b2016-06-30 17:24:44 +02001979 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001980 if (IS_ERR(prog))
1981 return prog;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001982 if (!bpf_prog_get_ok(prog, attach_type, attach_drv)) {
Daniel Borkmann113214b2016-06-30 17:24:44 +02001983 prog = ERR_PTR(-EINVAL);
1984 goto out;
1985 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001986
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001987 bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001988out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001989 fdput(f);
1990 return prog;
1991}
Daniel Borkmann113214b2016-06-30 17:24:44 +02001992
1993struct bpf_prog *bpf_prog_get(u32 ufd)
1994{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001995 return __bpf_prog_get(ufd, NULL, false);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001996}
1997
Jakub Kicinski248f3462017-11-03 13:56:20 -07001998struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001999 bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07002000{
Alexei Starovoitov4d220ed2018-04-28 19:56:37 -07002001 return __bpf_prog_get(ufd, &type, attach_drv);
Jakub Kicinski248f3462017-11-03 13:56:20 -07002002}
Jakub Kicinski6c8dfe22017-11-03 13:56:21 -07002003EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
Jakub Kicinski248f3462017-11-03 13:56:20 -07002004
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002005/* Initially all BPF programs could be loaded w/o specifying
2006 * expected_attach_type. Later for some of them specifying expected_attach_type
2007 * at load time became required so that program could be validated properly.
2008 * Programs of types that are allowed to be loaded both w/ and w/o (for
2009 * backward compatibility) expected_attach_type, should have the default attach
2010 * type assigned to expected_attach_type for the latter case, so that it can be
2011 * validated later at attach time.
2012 *
2013 * bpf_prog_load_fixup_attach_type() sets expected_attach_type in @attr if
2014 * prog type requires it but has some attach types that have to be backward
2015 * compatible.
2016 */
2017static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
2018{
2019 switch (attr->prog_type) {
2020 case BPF_PROG_TYPE_CGROUP_SOCK:
2021 /* Unfortunately BPF_ATTACH_TYPE_UNSPEC enumeration doesn't
2022 * exist so checking for non-zero is the way to go here.
2023 */
2024 if (!attr->expected_attach_type)
2025 attr->expected_attach_type =
2026 BPF_CGROUP_INET_SOCK_CREATE;
2027 break;
Kuniyuki Iwashimad5e4dda2021-06-12 21:32:22 +09002028 case BPF_PROG_TYPE_SK_REUSEPORT:
2029 if (!attr->expected_attach_type)
2030 attr->expected_attach_type =
2031 BPF_SK_REUSEPORT_SELECT;
2032 break;
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002033 }
2034}
2035
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002036static int
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002037bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
2038 enum bpf_attach_type expected_attach_type,
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002039 struct btf *attach_btf, u32 btf_id,
2040 struct bpf_prog *dst_prog)
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002041{
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002042 if (btf_id) {
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002043 if (btf_id > BTF_MAX_TYPE)
2044 return -EINVAL;
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002045
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002046 if (!attach_btf && !dst_prog)
2047 return -EINVAL;
2048
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002049 switch (prog_type) {
2050 case BPF_PROG_TYPE_TRACING:
KP Singh9e4e01d2020-03-29 01:43:52 +01002051 case BPF_PROG_TYPE_LSM:
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002052 case BPF_PROG_TYPE_STRUCT_OPS:
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002053 case BPF_PROG_TYPE_EXT:
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002054 break;
2055 default:
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002056 return -EINVAL;
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002057 }
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002058 }
2059
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002060 if (attach_btf && (!btf_id || dst_prog))
2061 return -EINVAL;
2062
2063 if (dst_prog && prog_type != BPF_PROG_TYPE_TRACING &&
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002064 prog_type != BPF_PROG_TYPE_EXT)
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002065 return -EINVAL;
2066
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002067 switch (prog_type) {
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002068 case BPF_PROG_TYPE_CGROUP_SOCK:
2069 switch (expected_attach_type) {
2070 case BPF_CGROUP_INET_SOCK_CREATE:
Stanislav Fomichevf5836742020-07-06 16:01:25 -07002071 case BPF_CGROUP_INET_SOCK_RELEASE:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002072 case BPF_CGROUP_INET4_POST_BIND:
2073 case BPF_CGROUP_INET6_POST_BIND:
2074 return 0;
2075 default:
2076 return -EINVAL;
2077 }
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002078 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2079 switch (expected_attach_type) {
2080 case BPF_CGROUP_INET4_BIND:
2081 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07002082 case BPF_CGROUP_INET4_CONNECT:
2083 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02002084 case BPF_CGROUP_INET4_GETPEERNAME:
2085 case BPF_CGROUP_INET6_GETPEERNAME:
2086 case BPF_CGROUP_INET4_GETSOCKNAME:
2087 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07002088 case BPF_CGROUP_UDP4_SENDMSG:
2089 case BPF_CGROUP_UDP6_SENDMSG:
Daniel Borkmann983695f2019-06-07 01:48:57 +02002090 case BPF_CGROUP_UDP4_RECVMSG:
2091 case BPF_CGROUP_UDP6_RECVMSG:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002092 return 0;
2093 default:
2094 return -EINVAL;
2095 }
brakmo5cf1e912019-05-28 16:59:36 -07002096 case BPF_PROG_TYPE_CGROUP_SKB:
2097 switch (expected_attach_type) {
2098 case BPF_CGROUP_INET_INGRESS:
2099 case BPF_CGROUP_INET_EGRESS:
2100 return 0;
2101 default:
2102 return -EINVAL;
2103 }
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07002104 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2105 switch (expected_attach_type) {
2106 case BPF_CGROUP_SETSOCKOPT:
2107 case BPF_CGROUP_GETSOCKOPT:
2108 return 0;
2109 default:
2110 return -EINVAL;
2111 }
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02002112 case BPF_PROG_TYPE_SK_LOOKUP:
2113 if (expected_attach_type == BPF_SK_LOOKUP)
2114 return 0;
2115 return -EINVAL;
Kuniyuki Iwashimad5e4dda2021-06-12 21:32:22 +09002116 case BPF_PROG_TYPE_SK_REUSEPORT:
2117 switch (expected_attach_type) {
2118 case BPF_SK_REUSEPORT_SELECT:
2119 case BPF_SK_REUSEPORT_SELECT_OR_MIGRATE:
2120 return 0;
2121 default:
2122 return -EINVAL;
2123 }
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07002124 case BPF_PROG_TYPE_SYSCALL:
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002125 case BPF_PROG_TYPE_EXT:
2126 if (expected_attach_type)
2127 return -EINVAL;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05002128 fallthrough;
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002129 default:
2130 return 0;
2131 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002132}
2133
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002134static bool is_net_admin_prog_type(enum bpf_prog_type prog_type)
2135{
2136 switch (prog_type) {
2137 case BPF_PROG_TYPE_SCHED_CLS:
2138 case BPF_PROG_TYPE_SCHED_ACT:
2139 case BPF_PROG_TYPE_XDP:
2140 case BPF_PROG_TYPE_LWT_IN:
2141 case BPF_PROG_TYPE_LWT_OUT:
2142 case BPF_PROG_TYPE_LWT_XMIT:
2143 case BPF_PROG_TYPE_LWT_SEG6LOCAL:
2144 case BPF_PROG_TYPE_SK_SKB:
2145 case BPF_PROG_TYPE_SK_MSG:
2146 case BPF_PROG_TYPE_LIRC_MODE2:
2147 case BPF_PROG_TYPE_FLOW_DISSECTOR:
2148 case BPF_PROG_TYPE_CGROUP_DEVICE:
2149 case BPF_PROG_TYPE_CGROUP_SOCK:
2150 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2151 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2152 case BPF_PROG_TYPE_CGROUP_SYSCTL:
2153 case BPF_PROG_TYPE_SOCK_OPS:
2154 case BPF_PROG_TYPE_EXT: /* extends any prog */
2155 return true;
2156 case BPF_PROG_TYPE_CGROUP_SKB:
2157 /* always unpriv */
2158 case BPF_PROG_TYPE_SK_REUSEPORT:
2159 /* equivalent to SOCKET_FILTER. need CAP_BPF only */
2160 default:
2161 return false;
2162 }
2163}
2164
2165static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
2166{
2167 switch (prog_type) {
2168 case BPF_PROG_TYPE_KPROBE:
2169 case BPF_PROG_TYPE_TRACEPOINT:
2170 case BPF_PROG_TYPE_PERF_EVENT:
2171 case BPF_PROG_TYPE_RAW_TRACEPOINT:
2172 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
2173 case BPF_PROG_TYPE_TRACING:
2174 case BPF_PROG_TYPE_LSM:
2175 case BPF_PROG_TYPE_STRUCT_OPS: /* has access to struct sock */
2176 case BPF_PROG_TYPE_EXT: /* extends any prog */
2177 return true;
2178 default:
2179 return false;
2180 }
2181}
2182
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002183/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov387544b2021-05-13 17:36:10 -07002184#define BPF_PROG_LOAD_LAST_FIELD fd_array
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002185
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07002186static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002187{
2188 enum bpf_prog_type type = attr->prog_type;
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002189 struct bpf_prog *prog, *dst_prog = NULL;
2190 struct btf *attach_btf = NULL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002191 int err;
2192 char license[128];
2193 bool is_gpl;
2194
2195 if (CHECK_ATTR(BPF_PROG_LOAD))
2196 return -EINVAL;
2197
Jiong Wangc240eff2019-05-24 23:25:16 +01002198 if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
2199 BPF_F_ANY_ALIGNMENT |
Alexei Starovoitov10d274e2019-08-22 22:52:12 -07002200 BPF_F_TEST_STATE_FREQ |
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07002201 BPF_F_SLEEPABLE |
Jiong Wangc240eff2019-05-24 23:25:16 +01002202 BPF_F_TEST_RND_HI32))
David S. Millere07b98d2017-05-10 11:38:07 -07002203 return -EINVAL;
2204
David Millere9ee9ef2018-11-30 21:08:14 -08002205 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
2206 (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002207 !bpf_capable())
David Millere9ee9ef2018-11-30 21:08:14 -08002208 return -EPERM;
2209
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002210 /* copy eBPF program license from user space */
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07002211 if (strncpy_from_bpfptr(license,
2212 make_bpfptr(attr->license, uattr.is_kernel),
2213 sizeof(license) - 1) < 0)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002214 return -EFAULT;
2215 license[sizeof(license) - 1] = 0;
2216
2217 /* eBPF programs must be GPL compatible to use GPL-ed functions */
2218 is_gpl = license_is_gpl_compatible(license);
2219
Alexei Starovoitovc04c0d22019-04-01 21:27:45 -07002220 if (attr->insn_cnt == 0 ||
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002221 attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
Daniel Borkmannef0915c2016-12-07 01:15:44 +01002222 return -E2BIG;
Chenbo Feng80b7d812017-05-31 18:16:00 -07002223 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
2224 type != BPF_PROG_TYPE_CGROUP_SKB &&
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002225 !bpf_capable())
2226 return -EPERM;
2227
Maciej Żenczykowskib338cb92020-06-20 14:26:16 -07002228 if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002229 return -EPERM;
2230 if (is_perfmon_prog_type(type) && !perfmon_capable())
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07002231 return -EPERM;
2232
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002233 /* attach_prog_fd/attach_btf_obj_fd can specify fd of either bpf_prog
2234 * or btf, we need to check which one it is
2235 */
2236 if (attr->attach_prog_fd) {
2237 dst_prog = bpf_prog_get(attr->attach_prog_fd);
2238 if (IS_ERR(dst_prog)) {
2239 dst_prog = NULL;
2240 attach_btf = btf_get_by_fd(attr->attach_btf_obj_fd);
2241 if (IS_ERR(attach_btf))
2242 return -EINVAL;
2243 if (!btf_is_kernel(attach_btf)) {
Andrii Nakryiko8bdd8e22020-12-07 22:43:26 -08002244 /* attaching through specifying bpf_prog's BTF
2245 * objects directly might be supported eventually
2246 */
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002247 btf_put(attach_btf);
Andrii Nakryiko8bdd8e22020-12-07 22:43:26 -08002248 return -ENOTSUPP;
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002249 }
2250 }
2251 } else if (attr->attach_btf_id) {
2252 /* fall back to vmlinux BTF, if BTF type ID is specified */
2253 attach_btf = bpf_get_btf_vmlinux();
2254 if (IS_ERR(attach_btf))
2255 return PTR_ERR(attach_btf);
2256 if (!attach_btf)
2257 return -EINVAL;
2258 btf_get(attach_btf);
2259 }
2260
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002261 bpf_prog_load_fixup_attach_type(attr);
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002262 if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002263 attach_btf, attr->attach_btf_id,
2264 dst_prog)) {
2265 if (dst_prog)
2266 bpf_prog_put(dst_prog);
2267 if (attach_btf)
2268 btf_put(attach_btf);
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002269 return -EINVAL;
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002270 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002271
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002272 /* plain bpf_prog allocation */
2273 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002274 if (!prog) {
2275 if (dst_prog)
2276 bpf_prog_put(dst_prog);
2277 if (attach_btf)
2278 btf_put(attach_btf);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002279 return -ENOMEM;
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002280 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002281
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002282 prog->expected_attach_type = attr->expected_attach_type;
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002283 prog->aux->attach_btf = attach_btf;
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002284 prog->aux->attach_btf_id = attr->attach_btf_id;
Andrii Nakryiko290248a2020-12-03 12:46:30 -08002285 prog->aux->dst_prog = dst_prog;
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002286 prog->aux->offload_requested = !!attr->prog_ifindex;
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07002287 prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002288
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002289 err = security_bpf_prog_alloc(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002290 if (err)
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002291 goto free_prog;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002292
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002293 prog->aux->user = get_current_user();
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002294 prog->len = attr->insn_cnt;
2295
2296 err = -EFAULT;
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07002297 if (copy_from_bpfptr(prog->insns,
2298 make_bpfptr(attr->insns, uattr.is_kernel),
2299 bpf_prog_insn_size(prog)) != 0)
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002300 goto free_prog_sec;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002301
2302 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +02002303 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002304
Andrii Nakryiko85192db2019-11-17 09:28:03 -08002305 atomic64_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +02002306 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002307
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002308 if (bpf_prog_is_dev_bound(prog->aux)) {
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07002309 err = bpf_prog_offload_init(prog, attr);
2310 if (err)
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002311 goto free_prog_sec;
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07002312 }
2313
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002314 /* find program type: socket_filter vs tracing_filter */
2315 err = find_prog_type(type, prog);
2316 if (err < 0)
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002317 goto free_prog_sec;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002318
Jason A. Donenfeld9285ec42019-06-21 22:32:48 +02002319 prog->aux->load_time = ktime_get_boottime_ns();
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -07002320 err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
2321 sizeof(attr->prog_name));
2322 if (err < 0)
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002323 goto free_prog_sec;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07002324
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002325 /* run eBPF verifier */
Yonghong Song838e9692018-11-19 15:29:11 -08002326 err = bpf_check(&prog, attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002327 if (err < 0)
2328 goto free_used_maps;
2329
Daniel Borkmann9facc332018-06-15 02:30:48 +02002330 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61ab2015-05-19 16:59:03 -07002331 if (err < 0)
2332 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002333
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07002334 err = bpf_prog_alloc_id(prog);
2335 if (err)
2336 goto free_used_maps;
2337
Daniel Borkmannc7517982019-08-23 22:14:23 +02002338 /* Upon success of bpf_prog_alloc_id(), the BPF prog is
2339 * effectively publicly exposed. However, retrieving via
2340 * bpf_prog_get_fd_by_id() will take another reference,
2341 * therefore it cannot be gone underneath us.
2342 *
2343 * Only for the time /after/ successful bpf_prog_new_fd()
2344 * and before returning to userspace, we might just hold
2345 * one reference and any parallel close on that fd could
2346 * rip everything out. Hence, below notifications must
2347 * happen before bpf_prog_new_fd().
2348 *
2349 * Also, any failure handling from this point onwards must
2350 * be using bpf_prog_put() given the program is exposed.
2351 */
Daniel Borkmann74451e662017-02-16 22:24:50 +01002352 bpf_prog_kallsyms_add(prog);
Song Liu6ee52e22019-01-17 08:15:15 -08002353 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
Daniel Borkmannbae141f2019-12-06 22:49:34 +01002354 bpf_audit_prog(prog, BPF_AUDIT_LOAD);
Daniel Borkmannc7517982019-08-23 22:14:23 +02002355
2356 err = bpf_prog_new_fd(prog);
2357 if (err < 0)
2358 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002359 return err;
2360
2361free_used_maps:
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02002362 /* In case we have subprogs, we need to wait for a grace
2363 * period before we can tear down JIT memory since symbols
2364 * are already exposed under kallsyms.
2365 */
2366 __bpf_prog_put_noref(prog, prog->aux->func_cnt);
2367 return err;
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002368free_prog_sec:
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002369 free_uid(prog->aux->user);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002370 security_bpf_prog_free(prog->aux);
Roman Gushchin3ac1f012020-12-01 13:58:59 -08002371free_prog:
Andrii Nakryiko22dc4a02020-12-03 12:46:29 -08002372 if (prog->aux->attach_btf)
2373 btf_put(prog->aux->attach_btf);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002374 bpf_prog_free(prog);
2375 return err;
2376}
2377
Chenbo Feng6e71b042017-10-18 13:00:22 -07002378#define BPF_OBJ_LAST_FIELD file_flags
Daniel Borkmannb2197752015-10-29 14:58:09 +01002379
2380static int bpf_obj_pin(const union bpf_attr *attr)
2381{
Chenbo Feng6e71b042017-10-18 13:00:22 -07002382 if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
Daniel Borkmannb2197752015-10-29 14:58:09 +01002383 return -EINVAL;
2384
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002385 return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +01002386}
2387
2388static int bpf_obj_get(const union bpf_attr *attr)
2389{
Chenbo Feng6e71b042017-10-18 13:00:22 -07002390 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 ||
2391 attr->file_flags & ~BPF_OBJ_FLAG_MASK)
Daniel Borkmannb2197752015-10-29 14:58:09 +01002392 return -EINVAL;
2393
Chenbo Feng6e71b042017-10-18 13:00:22 -07002394 return bpf_obj_get_user(u64_to_user_ptr(attr->pathname),
2395 attr->file_flags);
Daniel Borkmannb2197752015-10-29 14:58:09 +01002396}
2397
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002398void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002399 const struct bpf_link_ops *ops, struct bpf_prog *prog)
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002400{
2401 atomic64_set(&link->refcnt, 1);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002402 link->type = type;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002403 link->id = 0;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002404 link->ops = ops;
2405 link->prog = prog;
2406}
2407
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002408static void bpf_link_free_id(int id)
2409{
2410 if (!id)
2411 return;
2412
2413 spin_lock_bh(&link_idr_lock);
2414 idr_remove(&link_idr, id);
2415 spin_unlock_bh(&link_idr_lock);
2416}
2417
Andrii Nakryiko98868662020-03-12 17:21:28 -07002418/* Clean up bpf_link and corresponding anon_inode file and FD. After
2419 * anon_inode is created, bpf_link can't be just kfree()'d due to deferred
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002420 * anon_inode's release() call. This helper marksbpf_link as
2421 * defunct, releases anon_inode file and puts reserved FD. bpf_prog's refcnt
2422 * is not decremented, it's the responsibility of a calling code that failed
2423 * to complete bpf_link initialization.
Andrii Nakryiko98868662020-03-12 17:21:28 -07002424 */
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002425void bpf_link_cleanup(struct bpf_link_primer *primer)
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002426{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002427 primer->link->prog = NULL;
2428 bpf_link_free_id(primer->id);
2429 fput(primer->file);
2430 put_unused_fd(primer->fd);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002431}
2432
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002433void bpf_link_inc(struct bpf_link *link)
2434{
2435 atomic64_inc(&link->refcnt);
2436}
2437
2438/* bpf_link_free is guaranteed to be called from process context */
2439static void bpf_link_free(struct bpf_link *link)
2440{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002441 bpf_link_free_id(link->id);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002442 if (link->prog) {
2443 /* detach BPF program, clean up used resources */
2444 link->ops->release(link);
2445 bpf_prog_put(link->prog);
2446 }
2447 /* free bpf_link and its containing memory */
2448 link->ops->dealloc(link);
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002449}
2450
2451static void bpf_link_put_deferred(struct work_struct *work)
2452{
2453 struct bpf_link *link = container_of(work, struct bpf_link, work);
2454
2455 bpf_link_free(link);
2456}
2457
2458/* bpf_link_put can be called from atomic context, but ensures that resources
2459 * are freed from process context
2460 */
2461void bpf_link_put(struct bpf_link *link)
2462{
2463 if (!atomic64_dec_and_test(&link->refcnt))
2464 return;
2465
Alexei Starovoitovf00f2f72020-09-23 19:10:38 -07002466 if (in_atomic()) {
2467 INIT_WORK(&link->work, bpf_link_put_deferred);
2468 schedule_work(&link->work);
2469 } else {
2470 bpf_link_free(link);
2471 }
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002472}
2473
2474static int bpf_link_release(struct inode *inode, struct file *filp)
2475{
2476 struct bpf_link *link = filp->private_data;
2477
2478 bpf_link_put(link);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002479 return 0;
2480}
2481
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002482#ifdef CONFIG_PROC_FS
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002483#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
2484#define BPF_MAP_TYPE(_id, _ops)
2485#define BPF_LINK_TYPE(_id, _name) [_id] = #_name,
2486static const char *bpf_link_type_strs[] = {
2487 [BPF_LINK_TYPE_UNSPEC] = "<invalid>",
2488#include <linux/bpf_types.h>
2489};
2490#undef BPF_PROG_TYPE
2491#undef BPF_MAP_TYPE
2492#undef BPF_LINK_TYPE
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002493
2494static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
2495{
2496 const struct bpf_link *link = filp->private_data;
2497 const struct bpf_prog *prog = link->prog;
2498 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002499
2500 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
2501 seq_printf(m,
2502 "link_type:\t%s\n"
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002503 "link_id:\t%u\n"
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002504 "prog_tag:\t%s\n"
2505 "prog_id:\t%u\n",
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002506 bpf_link_type_strs[link->type],
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002507 link->id,
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002508 prog_tag,
2509 prog->aux->id);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002510 if (link->ops->show_fdinfo)
2511 link->ops->show_fdinfo(link, m);
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002512}
2513#endif
2514
Zou Wei6f302bf2020-04-23 10:32:40 +08002515static const struct file_operations bpf_link_fops = {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002516#ifdef CONFIG_PROC_FS
2517 .show_fdinfo = bpf_link_show_fdinfo,
2518#endif
2519 .release = bpf_link_release,
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002520 .read = bpf_dummy_read,
2521 .write = bpf_dummy_write,
2522};
2523
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002524static int bpf_link_alloc_id(struct bpf_link *link)
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002525{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002526 int id;
2527
2528 idr_preload(GFP_KERNEL);
2529 spin_lock_bh(&link_idr_lock);
2530 id = idr_alloc_cyclic(&link_idr, link, 1, INT_MAX, GFP_ATOMIC);
2531 spin_unlock_bh(&link_idr_lock);
2532 idr_preload_end();
2533
2534 return id;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002535}
2536
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002537/* Prepare bpf_link to be exposed to user-space by allocating anon_inode file,
2538 * reserving unused FD and allocating ID from link_idr. This is to be paired
2539 * with bpf_link_settle() to install FD and ID and expose bpf_link to
2540 * user-space, if bpf_link is successfully attached. If not, bpf_link and
2541 * pre-allocated resources are to be freed with bpf_cleanup() call. All the
2542 * transient state is passed around in struct bpf_link_primer.
2543 * This is preferred way to create and initialize bpf_link, especially when
2544 * there are complicated and expensive operations inbetween creating bpf_link
2545 * itself and attaching it to BPF hook. By using bpf_link_prime() and
2546 * bpf_link_settle() kernel code using bpf_link doesn't have to perform
2547 * expensive (and potentially failing) roll back operations in a rare case
2548 * that file, FD, or ID can't be allocated.
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002549 */
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002550int bpf_link_prime(struct bpf_link *link, struct bpf_link_primer *primer)
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002551{
2552 struct file *file;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002553 int fd, id;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002554
2555 fd = get_unused_fd_flags(O_CLOEXEC);
2556 if (fd < 0)
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002557 return fd;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002558
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002559
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002560 id = bpf_link_alloc_id(link);
2561 if (id < 0) {
2562 put_unused_fd(fd);
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002563 return id;
2564 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002565
2566 file = anon_inode_getfile("bpf_link", &bpf_link_fops, link, O_CLOEXEC);
2567 if (IS_ERR(file)) {
Andrii Nakryiko138c6762020-05-01 11:56:22 -07002568 bpf_link_free_id(id);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002569 put_unused_fd(fd);
Andrii Nakryiko138c6762020-05-01 11:56:22 -07002570 return PTR_ERR(file);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002571 }
2572
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002573 primer->link = link;
2574 primer->file = file;
2575 primer->fd = fd;
2576 primer->id = id;
2577 return 0;
2578}
2579
2580int bpf_link_settle(struct bpf_link_primer *primer)
2581{
2582 /* make bpf_link fetchable by ID */
2583 spin_lock_bh(&link_idr_lock);
2584 primer->link->id = primer->id;
2585 spin_unlock_bh(&link_idr_lock);
2586 /* make bpf_link fetchable by FD */
2587 fd_install(primer->fd, primer->file);
2588 /* pass through installed FD */
2589 return primer->fd;
2590}
2591
2592int bpf_link_new_fd(struct bpf_link *link)
2593{
2594 return anon_inode_getfd("bpf-link", &bpf_link_fops, link, O_CLOEXEC);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002595}
2596
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002597struct bpf_link *bpf_link_get_from_fd(u32 ufd)
2598{
2599 struct fd f = fdget(ufd);
2600 struct bpf_link *link;
2601
2602 if (!f.file)
2603 return ERR_PTR(-EBADF);
2604 if (f.file->f_op != &bpf_link_fops) {
2605 fdput(f);
2606 return ERR_PTR(-EINVAL);
2607 }
2608
2609 link = f.file->private_data;
2610 bpf_link_inc(link);
2611 fdput(f);
2612
2613 return link;
2614}
2615
2616struct bpf_tracing_link {
2617 struct bpf_link link;
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002618 enum bpf_attach_type attach_type;
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002619 struct bpf_trampoline *trampoline;
2620 struct bpf_prog *tgt_prog;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002621};
2622
2623static void bpf_tracing_link_release(struct bpf_link *link)
2624{
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002625 struct bpf_tracing_link *tr_link =
2626 container_of(link, struct bpf_tracing_link, link);
2627
2628 WARN_ON_ONCE(bpf_trampoline_unlink_prog(link->prog,
2629 tr_link->trampoline));
2630
2631 bpf_trampoline_put(tr_link->trampoline);
2632
2633 /* tgt_prog is NULL if target is a kernel function */
2634 if (tr_link->tgt_prog)
2635 bpf_prog_put(tr_link->tgt_prog);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002636}
2637
2638static void bpf_tracing_link_dealloc(struct bpf_link *link)
2639{
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002640 struct bpf_tracing_link *tr_link =
2641 container_of(link, struct bpf_tracing_link, link);
2642
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002643 kfree(tr_link);
2644}
2645
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002646static void bpf_tracing_link_show_fdinfo(const struct bpf_link *link,
2647 struct seq_file *seq)
2648{
2649 struct bpf_tracing_link *tr_link =
2650 container_of(link, struct bpf_tracing_link, link);
2651
2652 seq_printf(seq,
2653 "attach_type:\t%d\n",
2654 tr_link->attach_type);
2655}
2656
2657static int bpf_tracing_link_fill_link_info(const struct bpf_link *link,
2658 struct bpf_link_info *info)
2659{
2660 struct bpf_tracing_link *tr_link =
2661 container_of(link, struct bpf_tracing_link, link);
2662
2663 info->tracing.attach_type = tr_link->attach_type;
Toke Høiland-Jørgensen441e8c62021-04-13 11:16:06 +02002664 bpf_trampoline_unpack_key(tr_link->trampoline->key,
2665 &info->tracing.target_obj_id,
2666 &info->tracing.target_btf_id);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002667
2668 return 0;
2669}
2670
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002671static const struct bpf_link_ops bpf_tracing_link_lops = {
2672 .release = bpf_tracing_link_release,
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002673 .dealloc = bpf_tracing_link_dealloc,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002674 .show_fdinfo = bpf_tracing_link_show_fdinfo,
2675 .fill_link_info = bpf_tracing_link_fill_link_info,
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002676};
2677
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002678static int bpf_tracing_prog_attach(struct bpf_prog *prog,
2679 int tgt_prog_fd,
2680 u32 btf_id)
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002681{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002682 struct bpf_link_primer link_primer;
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002683 struct bpf_prog *tgt_prog = NULL;
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002684 struct bpf_trampoline *tr = NULL;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002685 struct bpf_tracing_link *link;
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002686 u64 key = 0;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002687 int err;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002688
KP Singh9e4e01d2020-03-29 01:43:52 +01002689 switch (prog->type) {
2690 case BPF_PROG_TYPE_TRACING:
2691 if (prog->expected_attach_type != BPF_TRACE_FENTRY &&
2692 prog->expected_attach_type != BPF_TRACE_FEXIT &&
2693 prog->expected_attach_type != BPF_MODIFY_RETURN) {
2694 err = -EINVAL;
2695 goto out_put_prog;
2696 }
2697 break;
2698 case BPF_PROG_TYPE_EXT:
2699 if (prog->expected_attach_type != 0) {
2700 err = -EINVAL;
2701 goto out_put_prog;
2702 }
2703 break;
2704 case BPF_PROG_TYPE_LSM:
2705 if (prog->expected_attach_type != BPF_LSM_MAC) {
2706 err = -EINVAL;
2707 goto out_put_prog;
2708 }
2709 break;
2710 default:
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002711 err = -EINVAL;
2712 goto out_put_prog;
2713 }
2714
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002715 if (!!tgt_prog_fd != !!btf_id) {
2716 err = -EINVAL;
2717 goto out_put_prog;
2718 }
2719
2720 if (tgt_prog_fd) {
2721 /* For now we only allow new targets for BPF_PROG_TYPE_EXT */
2722 if (prog->type != BPF_PROG_TYPE_EXT) {
2723 err = -EINVAL;
2724 goto out_put_prog;
2725 }
2726
2727 tgt_prog = bpf_prog_get(tgt_prog_fd);
2728 if (IS_ERR(tgt_prog)) {
2729 err = PTR_ERR(tgt_prog);
2730 tgt_prog = NULL;
2731 goto out_put_prog;
2732 }
2733
Andrii Nakryiko22dc4a02020-12-03 12:46:29 -08002734 key = bpf_trampoline_compute_key(tgt_prog, NULL, btf_id);
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002735 }
2736
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002737 link = kzalloc(sizeof(*link), GFP_USER);
2738 if (!link) {
2739 err = -ENOMEM;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002740 goto out_put_prog;
2741 }
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002742 bpf_link_init(&link->link, BPF_LINK_TYPE_TRACING,
2743 &bpf_tracing_link_lops, prog);
2744 link->attach_type = prog->expected_attach_type;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002745
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002746 mutex_lock(&prog->aux->dst_mutex);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002747
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002748 /* There are a few possible cases here:
2749 *
2750 * - if prog->aux->dst_trampoline is set, the program was just loaded
2751 * and not yet attached to anything, so we can use the values stored
2752 * in prog->aux
2753 *
2754 * - if prog->aux->dst_trampoline is NULL, the program has already been
2755 * attached to a target and its initial target was cleared (below)
2756 *
2757 * - if tgt_prog != NULL, the caller specified tgt_prog_fd +
2758 * target_btf_id using the link_create API.
2759 *
2760 * - if tgt_prog == NULL when this function was called using the old
Jiri Olsaf3a95072021-04-14 21:51:41 +02002761 * raw_tracepoint_open API, and we need a target from prog->aux
2762 *
2763 * - if prog->aux->dst_trampoline and tgt_prog is NULL, the program
2764 * was detached and is going for re-attachment.
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002765 */
2766 if (!prog->aux->dst_trampoline && !tgt_prog) {
Jiri Olsaf3a95072021-04-14 21:51:41 +02002767 /*
2768 * Allow re-attach for TRACING and LSM programs. If it's
2769 * currently linked, bpf_trampoline_link_prog will fail.
2770 * EXT programs need to specify tgt_prog_fd, so they
2771 * re-attach in separate code path.
2772 */
2773 if (prog->type != BPF_PROG_TYPE_TRACING &&
2774 prog->type != BPF_PROG_TYPE_LSM) {
2775 err = -EINVAL;
2776 goto out_unlock;
2777 }
2778 btf_id = prog->aux->attach_btf_id;
2779 key = bpf_trampoline_compute_key(NULL, prog->aux->attach_btf, btf_id);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002780 }
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002781
2782 if (!prog->aux->dst_trampoline ||
2783 (key && key != prog->aux->dst_trampoline->key)) {
2784 /* If there is no saved target, or the specified target is
2785 * different from the destination specified at load time, we
2786 * need a new trampoline and a check for compatibility
2787 */
2788 struct bpf_attach_target_info tgt_info = {};
2789
2790 err = bpf_check_attach_target(NULL, prog, tgt_prog, btf_id,
2791 &tgt_info);
2792 if (err)
2793 goto out_unlock;
2794
2795 tr = bpf_trampoline_get(key, &tgt_info);
2796 if (!tr) {
2797 err = -ENOMEM;
2798 goto out_unlock;
2799 }
2800 } else {
2801 /* The caller didn't specify a target, or the target was the
2802 * same as the destination supplied during program load. This
2803 * means we can reuse the trampoline and reference from program
2804 * load time, and there is no need to allocate a new one. This
2805 * can only happen once for any program, as the saved values in
2806 * prog->aux are cleared below.
2807 */
2808 tr = prog->aux->dst_trampoline;
2809 tgt_prog = prog->aux->dst_prog;
2810 }
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002811
2812 err = bpf_link_prime(&link->link, &link_primer);
2813 if (err)
2814 goto out_unlock;
2815
2816 err = bpf_trampoline_link_prog(prog, tr);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002817 if (err) {
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002818 bpf_link_cleanup(&link_primer);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002819 link = NULL;
2820 goto out_unlock;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002821 }
2822
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002823 link->tgt_prog = tgt_prog;
2824 link->trampoline = tr;
2825
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002826 /* Always clear the trampoline and target prog from prog->aux to make
2827 * sure the original attach destination is not kept alive after a
2828 * program is (re-)attached to another target.
2829 */
2830 if (prog->aux->dst_prog &&
2831 (tgt_prog_fd || tr != prog->aux->dst_trampoline))
2832 /* got extra prog ref from syscall, or attaching to different prog */
2833 bpf_prog_put(prog->aux->dst_prog);
2834 if (prog->aux->dst_trampoline && tr != prog->aux->dst_trampoline)
2835 /* we allocated a new trampoline, so free the old one */
2836 bpf_trampoline_put(prog->aux->dst_trampoline);
2837
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002838 prog->aux->dst_prog = NULL;
2839 prog->aux->dst_trampoline = NULL;
2840 mutex_unlock(&prog->aux->dst_mutex);
2841
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002842 return bpf_link_settle(&link_primer);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002843out_unlock:
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002844 if (tr && tr != prog->aux->dst_trampoline)
2845 bpf_trampoline_put(tr);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002846 mutex_unlock(&prog->aux->dst_mutex);
2847 kfree(link);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002848out_put_prog:
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002849 if (tgt_prog_fd && tgt_prog)
2850 bpf_prog_put(tgt_prog);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002851 return err;
2852}
2853
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002854struct bpf_raw_tp_link {
2855 struct bpf_link link;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002856 struct bpf_raw_event_map *btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002857};
2858
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002859static void bpf_raw_tp_link_release(struct bpf_link *link)
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002860{
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002861 struct bpf_raw_tp_link *raw_tp =
2862 container_of(link, struct bpf_raw_tp_link, link);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002863
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002864 bpf_probe_unregister(raw_tp->btp, raw_tp->link.prog);
Matt Mullinsa38d1102018-12-12 16:42:37 -08002865 bpf_put_raw_tracepoint(raw_tp->btp);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002866}
2867
2868static void bpf_raw_tp_link_dealloc(struct bpf_link *link)
2869{
2870 struct bpf_raw_tp_link *raw_tp =
2871 container_of(link, struct bpf_raw_tp_link, link);
2872
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002873 kfree(raw_tp);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002874}
2875
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002876static void bpf_raw_tp_link_show_fdinfo(const struct bpf_link *link,
2877 struct seq_file *seq)
2878{
2879 struct bpf_raw_tp_link *raw_tp_link =
2880 container_of(link, struct bpf_raw_tp_link, link);
2881
2882 seq_printf(seq,
2883 "tp_name:\t%s\n",
2884 raw_tp_link->btp->tp->name);
2885}
2886
2887static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link,
2888 struct bpf_link_info *info)
2889{
2890 struct bpf_raw_tp_link *raw_tp_link =
2891 container_of(link, struct bpf_raw_tp_link, link);
2892 char __user *ubuf = u64_to_user_ptr(info->raw_tracepoint.tp_name);
2893 const char *tp_name = raw_tp_link->btp->tp->name;
2894 u32 ulen = info->raw_tracepoint.tp_name_len;
2895 size_t tp_len = strlen(tp_name);
2896
Yonghong Songb4749592020-08-21 12:10:54 -07002897 if (!ulen ^ !ubuf)
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002898 return -EINVAL;
2899
2900 info->raw_tracepoint.tp_name_len = tp_len + 1;
2901
2902 if (!ubuf)
2903 return 0;
2904
2905 if (ulen >= tp_len + 1) {
2906 if (copy_to_user(ubuf, tp_name, tp_len + 1))
2907 return -EFAULT;
2908 } else {
2909 char zero = '\0';
2910
2911 if (copy_to_user(ubuf, tp_name, ulen - 1))
2912 return -EFAULT;
2913 if (put_user(zero, ubuf + ulen - 1))
2914 return -EFAULT;
2915 return -ENOSPC;
2916 }
2917
2918 return 0;
2919}
2920
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002921static const struct bpf_link_ops bpf_raw_tp_link_lops = {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002922 .release = bpf_raw_tp_link_release,
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002923 .dealloc = bpf_raw_tp_link_dealloc,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002924 .show_fdinfo = bpf_raw_tp_link_show_fdinfo,
2925 .fill_link_info = bpf_raw_tp_link_fill_link_info,
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002926};
2927
Andrii Nakryikob89fbfb2021-08-15 00:05:57 -07002928#ifdef CONFIG_PERF_EVENTS
2929struct bpf_perf_link {
2930 struct bpf_link link;
2931 struct file *perf_file;
2932};
2933
2934static void bpf_perf_link_release(struct bpf_link *link)
2935{
2936 struct bpf_perf_link *perf_link = container_of(link, struct bpf_perf_link, link);
2937 struct perf_event *event = perf_link->perf_file->private_data;
2938
2939 perf_event_free_bpf_prog(event);
2940 fput(perf_link->perf_file);
2941}
2942
2943static void bpf_perf_link_dealloc(struct bpf_link *link)
2944{
2945 struct bpf_perf_link *perf_link = container_of(link, struct bpf_perf_link, link);
2946
2947 kfree(perf_link);
2948}
2949
2950static const struct bpf_link_ops bpf_perf_link_lops = {
2951 .release = bpf_perf_link_release,
2952 .dealloc = bpf_perf_link_dealloc,
2953};
2954
2955static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
2956{
2957 struct bpf_link_primer link_primer;
2958 struct bpf_perf_link *link;
2959 struct perf_event *event;
2960 struct file *perf_file;
2961 int err;
2962
2963 if (attr->link_create.flags)
2964 return -EINVAL;
2965
2966 perf_file = perf_event_get(attr->link_create.target_fd);
2967 if (IS_ERR(perf_file))
2968 return PTR_ERR(perf_file);
2969
2970 link = kzalloc(sizeof(*link), GFP_USER);
2971 if (!link) {
2972 err = -ENOMEM;
2973 goto out_put_file;
2974 }
2975 bpf_link_init(&link->link, BPF_LINK_TYPE_PERF_EVENT, &bpf_perf_link_lops, prog);
2976 link->perf_file = perf_file;
2977
2978 err = bpf_link_prime(&link->link, &link_primer);
2979 if (err) {
2980 kfree(link);
2981 goto out_put_file;
2982 }
2983
2984 event = perf_file->private_data;
Andrii Nakryiko82e6b1e2021-08-15 00:05:58 -07002985 err = perf_event_set_bpf_prog(event, prog, attr->link_create.perf_event.bpf_cookie);
Andrii Nakryikob89fbfb2021-08-15 00:05:57 -07002986 if (err) {
2987 bpf_link_cleanup(&link_primer);
2988 goto out_put_file;
2989 }
2990 /* perf_event_set_bpf_prog() doesn't take its own refcnt on prog */
2991 bpf_prog_inc(prog);
2992
2993 return bpf_link_settle(&link_primer);
2994
2995out_put_file:
2996 fput(perf_file);
2997 return err;
2998}
2999#endif /* CONFIG_PERF_EVENTS */
3000
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003001#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
3002
3003static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
3004{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003005 struct bpf_link_primer link_primer;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003006 struct bpf_raw_tp_link *link;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003007 struct bpf_raw_event_map *btp;
3008 struct bpf_prog *prog;
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003009 const char *tp_name;
3010 char buf[128];
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003011 int err;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003012
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003013 if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
3014 return -EINVAL;
3015
3016 prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
3017 if (IS_ERR(prog))
3018 return PTR_ERR(prog);
3019
KP Singh9e4e01d2020-03-29 01:43:52 +01003020 switch (prog->type) {
3021 case BPF_PROG_TYPE_TRACING:
3022 case BPF_PROG_TYPE_EXT:
3023 case BPF_PROG_TYPE_LSM:
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003024 if (attr->raw_tracepoint.name) {
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08003025 /* The attach point for this category of programs
3026 * should be specified via btf_id during program load.
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003027 */
3028 err = -EINVAL;
3029 goto out_put_prog;
3030 }
KP Singh9e4e01d2020-03-29 01:43:52 +01003031 if (prog->type == BPF_PROG_TYPE_TRACING &&
3032 prog->expected_attach_type == BPF_TRACE_RAW_TP) {
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08003033 tp_name = prog->aux->attach_func_name;
KP Singh9e4e01d2020-03-29 01:43:52 +01003034 break;
3035 }
Jiri Olsa55410752021-01-11 20:16:50 +01003036 err = bpf_tracing_prog_attach(prog, 0, 0);
3037 if (err >= 0)
3038 return err;
3039 goto out_put_prog;
KP Singh9e4e01d2020-03-29 01:43:52 +01003040 case BPF_PROG_TYPE_RAW_TRACEPOINT:
3041 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003042 if (strncpy_from_user(buf,
3043 u64_to_user_ptr(attr->raw_tracepoint.name),
3044 sizeof(buf) - 1) < 0) {
3045 err = -EFAULT;
3046 goto out_put_prog;
3047 }
3048 buf[sizeof(buf) - 1] = 0;
3049 tp_name = buf;
KP Singh9e4e01d2020-03-29 01:43:52 +01003050 break;
3051 default:
3052 err = -EINVAL;
3053 goto out_put_prog;
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003054 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003055
Matt Mullinsa38d1102018-12-12 16:42:37 -08003056 btp = bpf_get_raw_tracepoint(tp_name);
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003057 if (!btp) {
3058 err = -ENOENT;
3059 goto out_put_prog;
3060 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003061
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003062 link = kzalloc(sizeof(*link), GFP_USER);
3063 if (!link) {
Matt Mullinsa38d1102018-12-12 16:42:37 -08003064 err = -ENOMEM;
3065 goto out_put_btp;
3066 }
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003067 bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT,
3068 &bpf_raw_tp_link_lops, prog);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003069 link->btp = btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003070
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003071 err = bpf_link_prime(&link->link, &link_primer);
3072 if (err) {
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003073 kfree(link);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003074 goto out_put_btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003075 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003076
3077 err = bpf_probe_register(link->btp, prog);
3078 if (err) {
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003079 bpf_link_cleanup(&link_primer);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07003080 goto out_put_btp;
3081 }
3082
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003083 return bpf_link_settle(&link_primer);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003084
Matt Mullinsa38d1102018-12-12 16:42:37 -08003085out_put_btp:
3086 bpf_put_raw_tracepoint(btp);
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07003087out_put_prog:
3088 bpf_prog_put(prog);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07003089 return err;
3090}
3091
Anders Roxell33491582018-04-03 14:09:47 +02003092static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
3093 enum bpf_attach_type attach_type)
3094{
3095 switch (prog->type) {
3096 case BPF_PROG_TYPE_CGROUP_SOCK:
3097 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07003098 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02003099 case BPF_PROG_TYPE_SK_LOOKUP:
Anders Roxell33491582018-04-03 14:09:47 +02003100 return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
brakmo5cf1e912019-05-28 16:59:36 -07003101 case BPF_PROG_TYPE_CGROUP_SKB:
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07003102 if (!capable(CAP_NET_ADMIN))
3103 /* cg-skb progs can be loaded by unpriv user.
3104 * check permissions at attach time.
3105 */
3106 return -EPERM;
brakmo5cf1e912019-05-28 16:59:36 -07003107 return prog->enforce_expected_attach_type &&
3108 prog->expected_attach_type != attach_type ?
3109 -EINVAL : 0;
Anders Roxell33491582018-04-03 14:09:47 +02003110 default:
3111 return 0;
3112 }
3113}
3114
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003115static enum bpf_prog_type
3116attach_type_to_prog_type(enum bpf_attach_type attach_type)
3117{
3118 switch (attach_type) {
3119 case BPF_CGROUP_INET_INGRESS:
3120 case BPF_CGROUP_INET_EGRESS:
3121 return BPF_PROG_TYPE_CGROUP_SKB;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003122 case BPF_CGROUP_INET_SOCK_CREATE:
Stanislav Fomichevf5836742020-07-06 16:01:25 -07003123 case BPF_CGROUP_INET_SOCK_RELEASE:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003124 case BPF_CGROUP_INET4_POST_BIND:
3125 case BPF_CGROUP_INET6_POST_BIND:
3126 return BPF_PROG_TYPE_CGROUP_SOCK;
3127 case BPF_CGROUP_INET4_BIND:
3128 case BPF_CGROUP_INET6_BIND:
3129 case BPF_CGROUP_INET4_CONNECT:
3130 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02003131 case BPF_CGROUP_INET4_GETPEERNAME:
3132 case BPF_CGROUP_INET6_GETPEERNAME:
3133 case BPF_CGROUP_INET4_GETSOCKNAME:
3134 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003135 case BPF_CGROUP_UDP4_SENDMSG:
3136 case BPF_CGROUP_UDP6_SENDMSG:
3137 case BPF_CGROUP_UDP4_RECVMSG:
3138 case BPF_CGROUP_UDP6_RECVMSG:
3139 return BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
3140 case BPF_CGROUP_SOCK_OPS:
3141 return BPF_PROG_TYPE_SOCK_OPS;
3142 case BPF_CGROUP_DEVICE:
3143 return BPF_PROG_TYPE_CGROUP_DEVICE;
3144 case BPF_SK_MSG_VERDICT:
3145 return BPF_PROG_TYPE_SK_MSG;
3146 case BPF_SK_SKB_STREAM_PARSER:
3147 case BPF_SK_SKB_STREAM_VERDICT:
Cong Wanga7ba4552021-03-30 19:32:30 -07003148 case BPF_SK_SKB_VERDICT:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003149 return BPF_PROG_TYPE_SK_SKB;
3150 case BPF_LIRC_MODE2:
3151 return BPF_PROG_TYPE_LIRC_MODE2;
3152 case BPF_FLOW_DISSECTOR:
3153 return BPF_PROG_TYPE_FLOW_DISSECTOR;
3154 case BPF_CGROUP_SYSCTL:
3155 return BPF_PROG_TYPE_CGROUP_SYSCTL;
3156 case BPF_CGROUP_GETSOCKOPT:
3157 case BPF_CGROUP_SETSOCKOPT:
3158 return BPF_PROG_TYPE_CGROUP_SOCKOPT;
Yonghong Songde4e05c2020-05-09 10:59:01 -07003159 case BPF_TRACE_ITER:
3160 return BPF_PROG_TYPE_TRACING;
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02003161 case BPF_SK_LOOKUP:
3162 return BPF_PROG_TYPE_SK_LOOKUP;
Andrii Nakryikoaa8d3a72020-07-21 23:45:57 -07003163 case BPF_XDP:
3164 return BPF_PROG_TYPE_XDP;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003165 default:
3166 return BPF_PROG_TYPE_UNSPEC;
3167 }
3168}
3169
Andrey Ignatov7dd68b32019-12-18 23:44:35 -08003170#define BPF_PROG_ATTACH_LAST_FIELD replace_bpf_fd
John Fastabend174a79f2017-08-15 22:32:47 -07003171
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003172#define BPF_F_ATTACH_MASK \
Andrey Ignatov7dd68b32019-12-18 23:44:35 -08003173 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI | BPF_F_REPLACE)
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003174
Daniel Mackf4324552016-11-23 16:52:27 +01003175static int bpf_prog_attach(const union bpf_attr *attr)
3176{
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003177 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01003178 struct bpf_prog *prog;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003179 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01003180
Daniel Mackf4324552016-11-23 16:52:27 +01003181 if (CHECK_ATTR(BPF_PROG_ATTACH))
3182 return -EINVAL;
3183
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003184 if (attr->attach_flags & ~BPF_F_ATTACH_MASK)
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003185 return -EINVAL;
3186
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003187 ptype = attach_type_to_prog_type(attr->attach_type);
3188 if (ptype == BPF_PROG_TYPE_UNSPEC)
Daniel Mackf4324552016-11-23 16:52:27 +01003189 return -EINVAL;
Daniel Mackf4324552016-11-23 16:52:27 +01003190
David Ahernb2cd1252016-12-01 08:48:03 -08003191 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
3192 if (IS_ERR(prog))
3193 return PTR_ERR(prog);
3194
Andrey Ignatov5e43f892018-03-30 15:08:00 -07003195 if (bpf_prog_attach_check_attach_type(prog, attr->attach_type)) {
3196 bpf_prog_put(prog);
3197 return -EINVAL;
3198 }
3199
Sean Youngfdb5c452018-06-19 00:04:24 +01003200 switch (ptype) {
3201 case BPF_PROG_TYPE_SK_SKB:
3202 case BPF_PROG_TYPE_SK_MSG:
Daniel Borkmann604326b2018-10-13 02:45:58 +02003203 ret = sock_map_get_from_fd(attr, prog);
Sean Youngfdb5c452018-06-19 00:04:24 +01003204 break;
3205 case BPF_PROG_TYPE_LIRC_MODE2:
3206 ret = lirc_prog_attach(attr, prog);
3207 break;
Petar Penkovd58e4682018-09-14 07:46:18 -07003208 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02003209 ret = netns_bpf_prog_attach(attr, prog);
Petar Penkovd58e4682018-09-14 07:46:18 -07003210 break;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003211 case BPF_PROG_TYPE_CGROUP_DEVICE:
3212 case BPF_PROG_TYPE_CGROUP_SKB:
3213 case BPF_PROG_TYPE_CGROUP_SOCK:
3214 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3215 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3216 case BPF_PROG_TYPE_CGROUP_SYSCTL:
3217 case BPF_PROG_TYPE_SOCK_OPS:
Sean Youngfdb5c452018-06-19 00:04:24 +01003218 ret = cgroup_bpf_prog_attach(attr, ptype, prog);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003219 break;
3220 default:
3221 ret = -EINVAL;
David Ahernb2cd1252016-12-01 08:48:03 -08003222 }
3223
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003224 if (ret)
3225 bpf_prog_put(prog);
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003226 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01003227}
3228
3229#define BPF_PROG_DETACH_LAST_FIELD attach_type
3230
3231static int bpf_prog_detach(const union bpf_attr *attr)
3232{
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003233 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01003234
Daniel Mackf4324552016-11-23 16:52:27 +01003235 if (CHECK_ATTR(BPF_PROG_DETACH))
3236 return -EINVAL;
3237
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003238 ptype = attach_type_to_prog_type(attr->attach_type);
3239
3240 switch (ptype) {
3241 case BPF_PROG_TYPE_SK_MSG:
3242 case BPF_PROG_TYPE_SK_SKB:
Lorenz Bauerbb0de312020-06-29 10:56:28 +01003243 return sock_map_prog_detach(attr, ptype);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003244 case BPF_PROG_TYPE_LIRC_MODE2:
Sean Youngf4364dc2018-05-27 12:24:09 +01003245 return lirc_prog_detach(attr);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003246 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Lorenz Bauer4ac2add2020-06-29 10:56:26 +01003247 return netns_bpf_prog_detach(attr, ptype);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003248 case BPF_PROG_TYPE_CGROUP_DEVICE:
3249 case BPF_PROG_TYPE_CGROUP_SKB:
3250 case BPF_PROG_TYPE_CGROUP_SOCK:
3251 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3252 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3253 case BPF_PROG_TYPE_CGROUP_SYSCTL:
3254 case BPF_PROG_TYPE_SOCK_OPS:
3255 return cgroup_bpf_prog_detach(attr, ptype);
Daniel Mackf4324552016-11-23 16:52:27 +01003256 default:
3257 return -EINVAL;
3258 }
Daniel Mackf4324552016-11-23 16:52:27 +01003259}
Lawrence Brakmo40304b22017-06-30 20:02:40 -07003260
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003261#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
3262
3263static int bpf_prog_query(const union bpf_attr *attr,
3264 union bpf_attr __user *uattr)
3265{
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003266 if (!capable(CAP_NET_ADMIN))
3267 return -EPERM;
3268 if (CHECK_ATTR(BPF_PROG_QUERY))
3269 return -EINVAL;
3270 if (attr->query.query_flags & ~BPF_F_QUERY_EFFECTIVE)
3271 return -EINVAL;
3272
3273 switch (attr->query.attach_type) {
3274 case BPF_CGROUP_INET_INGRESS:
3275 case BPF_CGROUP_INET_EGRESS:
3276 case BPF_CGROUP_INET_SOCK_CREATE:
Stanislav Fomichevf5836742020-07-06 16:01:25 -07003277 case BPF_CGROUP_INET_SOCK_RELEASE:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07003278 case BPF_CGROUP_INET4_BIND:
3279 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07003280 case BPF_CGROUP_INET4_POST_BIND:
3281 case BPF_CGROUP_INET6_POST_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07003282 case BPF_CGROUP_INET4_CONNECT:
3283 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02003284 case BPF_CGROUP_INET4_GETPEERNAME:
3285 case BPF_CGROUP_INET6_GETPEERNAME:
3286 case BPF_CGROUP_INET4_GETSOCKNAME:
3287 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07003288 case BPF_CGROUP_UDP4_SENDMSG:
3289 case BPF_CGROUP_UDP6_SENDMSG:
Daniel Borkmann983695f2019-06-07 01:48:57 +02003290 case BPF_CGROUP_UDP4_RECVMSG:
3291 case BPF_CGROUP_UDP6_RECVMSG:
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003292 case BPF_CGROUP_SOCK_OPS:
Roman Gushchinebc614f2017-11-05 08:15:32 -05003293 case BPF_CGROUP_DEVICE:
Andrey Ignatov7b146ce2019-02-27 12:59:24 -08003294 case BPF_CGROUP_SYSCTL:
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07003295 case BPF_CGROUP_GETSOCKOPT:
3296 case BPF_CGROUP_SETSOCKOPT:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003297 return cgroup_bpf_prog_query(attr, uattr);
Sean Youngf4364dc2018-05-27 12:24:09 +01003298 case BPF_LIRC_MODE2:
3299 return lirc_prog_query(attr, uattr);
Stanislav Fomichev118c8e92019-04-25 14:37:23 -07003300 case BPF_FLOW_DISSECTOR:
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02003301 case BPF_SK_LOOKUP:
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02003302 return netns_bpf_prog_query(attr, uattr);
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003303 default:
3304 return -EINVAL;
3305 }
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003306}
Daniel Mackf4324552016-11-23 16:52:27 +01003307
Song Liu1b4d60e2020-09-25 13:54:29 -07003308#define BPF_PROG_TEST_RUN_LAST_FIELD test.cpu
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07003309
3310static int bpf_prog_test_run(const union bpf_attr *attr,
3311 union bpf_attr __user *uattr)
3312{
3313 struct bpf_prog *prog;
3314 int ret = -ENOTSUPP;
3315
3316 if (CHECK_ATTR(BPF_PROG_TEST_RUN))
3317 return -EINVAL;
3318
Stanislav Fomichevb0b93952019-04-09 11:49:09 -07003319 if ((attr->test.ctx_size_in && !attr->test.ctx_in) ||
3320 (!attr->test.ctx_size_in && attr->test.ctx_in))
3321 return -EINVAL;
3322
3323 if ((attr->test.ctx_size_out && !attr->test.ctx_out) ||
3324 (!attr->test.ctx_size_out && attr->test.ctx_out))
3325 return -EINVAL;
3326
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07003327 prog = bpf_prog_get(attr->test.prog_fd);
3328 if (IS_ERR(prog))
3329 return PTR_ERR(prog);
3330
3331 if (prog->aux->ops->test_run)
3332 ret = prog->aux->ops->test_run(prog, attr, uattr);
3333
3334 bpf_prog_put(prog);
3335 return ret;
3336}
3337
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07003338#define BPF_OBJ_GET_NEXT_ID_LAST_FIELD next_id
3339
3340static int bpf_obj_get_next_id(const union bpf_attr *attr,
3341 union bpf_attr __user *uattr,
3342 struct idr *idr,
3343 spinlock_t *lock)
3344{
3345 u32 next_id = attr->start_id;
3346 int err = 0;
3347
3348 if (CHECK_ATTR(BPF_OBJ_GET_NEXT_ID) || next_id >= INT_MAX)
3349 return -EINVAL;
3350
3351 if (!capable(CAP_SYS_ADMIN))
3352 return -EPERM;
3353
3354 next_id++;
3355 spin_lock_bh(lock);
3356 if (!idr_get_next(idr, &next_id))
3357 err = -ENOENT;
3358 spin_unlock_bh(lock);
3359
3360 if (!err)
3361 err = put_user(next_id, &uattr->next_id);
3362
3363 return err;
3364}
3365
Yonghong Song6086d292020-05-09 10:59:09 -07003366struct bpf_map *bpf_map_get_curr_or_next(u32 *id)
3367{
3368 struct bpf_map *map;
3369
3370 spin_lock_bh(&map_idr_lock);
3371again:
3372 map = idr_get_next(&map_idr, id);
3373 if (map) {
3374 map = __bpf_map_inc_not_zero(map, false);
3375 if (IS_ERR(map)) {
3376 (*id)++;
3377 goto again;
3378 }
3379 }
3380 spin_unlock_bh(&map_idr_lock);
3381
3382 return map;
3383}
3384
Alexei Starovoitova228a642020-07-01 18:10:18 -07003385struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id)
3386{
3387 struct bpf_prog *prog;
3388
3389 spin_lock_bh(&prog_idr_lock);
3390again:
3391 prog = idr_get_next(&prog_idr, id);
3392 if (prog) {
3393 prog = bpf_prog_inc_not_zero(prog);
3394 if (IS_ERR(prog)) {
3395 (*id)++;
3396 goto again;
3397 }
3398 }
3399 spin_unlock_bh(&prog_idr_lock);
3400
3401 return prog;
3402}
3403
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003404#define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
3405
Björn Töpel7e6897f2019-12-13 18:51:09 +01003406struct bpf_prog *bpf_prog_by_id(u32 id)
3407{
3408 struct bpf_prog *prog;
3409
3410 if (!id)
3411 return ERR_PTR(-ENOENT);
3412
3413 spin_lock_bh(&prog_idr_lock);
3414 prog = idr_find(&prog_idr, id);
3415 if (prog)
3416 prog = bpf_prog_inc_not_zero(prog);
3417 else
3418 prog = ERR_PTR(-ENOENT);
3419 spin_unlock_bh(&prog_idr_lock);
3420 return prog;
3421}
3422
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003423static int bpf_prog_get_fd_by_id(const union bpf_attr *attr)
3424{
3425 struct bpf_prog *prog;
3426 u32 id = attr->prog_id;
3427 int fd;
3428
3429 if (CHECK_ATTR(BPF_PROG_GET_FD_BY_ID))
3430 return -EINVAL;
3431
3432 if (!capable(CAP_SYS_ADMIN))
3433 return -EPERM;
3434
Björn Töpel7e6897f2019-12-13 18:51:09 +01003435 prog = bpf_prog_by_id(id);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003436 if (IS_ERR(prog))
3437 return PTR_ERR(prog);
3438
3439 fd = bpf_prog_new_fd(prog);
3440 if (fd < 0)
3441 bpf_prog_put(prog);
3442
3443 return fd;
3444}
3445
Chenbo Feng6e71b042017-10-18 13:00:22 -07003446#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD open_flags
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003447
3448static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
3449{
3450 struct bpf_map *map;
3451 u32 id = attr->map_id;
Chenbo Feng6e71b042017-10-18 13:00:22 -07003452 int f_flags;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003453 int fd;
3454
Chenbo Feng6e71b042017-10-18 13:00:22 -07003455 if (CHECK_ATTR(BPF_MAP_GET_FD_BY_ID) ||
3456 attr->open_flags & ~BPF_OBJ_FLAG_MASK)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003457 return -EINVAL;
3458
3459 if (!capable(CAP_SYS_ADMIN))
3460 return -EPERM;
3461
Chenbo Feng6e71b042017-10-18 13:00:22 -07003462 f_flags = bpf_get_file_flag(attr->open_flags);
3463 if (f_flags < 0)
3464 return f_flags;
3465
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003466 spin_lock_bh(&map_idr_lock);
3467 map = idr_find(&map_idr, id);
3468 if (map)
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07003469 map = __bpf_map_inc_not_zero(map, true);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003470 else
3471 map = ERR_PTR(-ENOENT);
3472 spin_unlock_bh(&map_idr_lock);
3473
3474 if (IS_ERR(map))
3475 return PTR_ERR(map);
3476
Chenbo Feng6e71b042017-10-18 13:00:22 -07003477 fd = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003478 if (fd < 0)
Peng Sun781e6282019-02-26 22:15:37 +08003479 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003480
3481 return fd;
3482}
3483
Daniel Borkmann7105e822017-12-20 13:42:57 +01003484static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003485 unsigned long addr, u32 *off,
3486 u32 *type)
Daniel Borkmann7105e822017-12-20 13:42:57 +01003487{
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003488 const struct bpf_map *map;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003489 int i;
3490
YiFei Zhu984fe942020-09-15 16:45:39 -07003491 mutex_lock(&prog->aux->used_maps_mutex);
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003492 for (i = 0, *off = 0; i < prog->aux->used_map_cnt; i++) {
3493 map = prog->aux->used_maps[i];
3494 if (map == (void *)addr) {
3495 *type = BPF_PSEUDO_MAP_FD;
YiFei Zhu984fe942020-09-15 16:45:39 -07003496 goto out;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003497 }
3498 if (!map->ops->map_direct_value_meta)
3499 continue;
3500 if (!map->ops->map_direct_value_meta(map, addr, off)) {
3501 *type = BPF_PSEUDO_MAP_VALUE;
YiFei Zhu984fe942020-09-15 16:45:39 -07003502 goto out;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003503 }
3504 }
YiFei Zhu984fe942020-09-15 16:45:39 -07003505 map = NULL;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003506
YiFei Zhu984fe942020-09-15 16:45:39 -07003507out:
3508 mutex_unlock(&prog->aux->used_maps_mutex);
3509 return map;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003510}
3511
Kees Cook63960262020-07-02 15:45:23 -07003512static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog,
3513 const struct cred *f_cred)
Daniel Borkmann7105e822017-12-20 13:42:57 +01003514{
3515 const struct bpf_map *map;
3516 struct bpf_insn *insns;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003517 u32 off, type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003518 u64 imm;
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003519 u8 code;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003520 int i;
3521
3522 insns = kmemdup(prog->insnsi, bpf_prog_insn_size(prog),
3523 GFP_USER);
3524 if (!insns)
3525 return insns;
3526
3527 for (i = 0; i < prog->len; i++) {
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003528 code = insns[i].code;
3529
3530 if (code == (BPF_JMP | BPF_TAIL_CALL)) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003531 insns[i].code = BPF_JMP | BPF_CALL;
3532 insns[i].imm = BPF_FUNC_tail_call;
3533 /* fall-through */
3534 }
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003535 if (code == (BPF_JMP | BPF_CALL) ||
3536 code == (BPF_JMP | BPF_CALL_ARGS)) {
3537 if (code == (BPF_JMP | BPF_CALL_ARGS))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003538 insns[i].code = BPF_JMP | BPF_CALL;
Kees Cook63960262020-07-02 15:45:23 -07003539 if (!bpf_dump_raw_ok(f_cred))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003540 insns[i].imm = 0;
3541 continue;
3542 }
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003543 if (BPF_CLASS(code) == BPF_LDX && BPF_MODE(code) == BPF_PROBE_MEM) {
3544 insns[i].code = BPF_LDX | BPF_SIZE(code) | BPF_MEM;
3545 continue;
3546 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01003547
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003548 if (code != (BPF_LD | BPF_IMM | BPF_DW))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003549 continue;
3550
3551 imm = ((u64)insns[i + 1].imm << 32) | (u32)insns[i].imm;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003552 map = bpf_map_from_imm(prog, imm, &off, &type);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003553 if (map) {
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003554 insns[i].src_reg = type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003555 insns[i].imm = map->id;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003556 insns[i + 1].imm = off;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003557 continue;
3558 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01003559 }
3560
3561 return insns;
3562}
3563
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003564static int set_info_rec_size(struct bpf_prog_info *info)
3565{
3566 /*
3567 * Ensure info.*_rec_size is the same as kernel expected size
3568 *
3569 * or
3570 *
3571 * Only allow zero *_rec_size if both _rec_size and _cnt are
3572 * zero. In this case, the kernel will set the expected
3573 * _rec_size back to the info.
3574 */
3575
Yonghong Song11d8b822018-12-10 14:14:08 -08003576 if ((info->nr_func_info || info->func_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003577 info->func_info_rec_size != sizeof(struct bpf_func_info))
3578 return -EINVAL;
3579
Yonghong Song11d8b822018-12-10 14:14:08 -08003580 if ((info->nr_line_info || info->line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003581 info->line_info_rec_size != sizeof(struct bpf_line_info))
3582 return -EINVAL;
3583
Yonghong Song11d8b822018-12-10 14:14:08 -08003584 if ((info->nr_jited_line_info || info->jited_line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003585 info->jited_line_info_rec_size != sizeof(__u64))
3586 return -EINVAL;
3587
3588 info->func_info_rec_size = sizeof(struct bpf_func_info);
3589 info->line_info_rec_size = sizeof(struct bpf_line_info);
3590 info->jited_line_info_rec_size = sizeof(__u64);
3591
3592 return 0;
3593}
3594
Kees Cook63960262020-07-02 15:45:23 -07003595static int bpf_prog_get_info_by_fd(struct file *file,
3596 struct bpf_prog *prog,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003597 const union bpf_attr *attr,
3598 union bpf_attr __user *uattr)
3599{
3600 struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003601 struct bpf_prog_info info;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003602 u32 info_len = attr->info.info_len;
Eric Dumazet61a0aba2021-10-26 14:41:33 -07003603 struct bpf_prog_kstats stats;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003604 char __user *uinsns;
3605 u32 ulen;
3606 int err;
3607
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07003608 err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003609 if (err)
3610 return err;
3611 info_len = min_t(u32, sizeof(info), info_len);
3612
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003613 memset(&info, 0, sizeof(info));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003614 if (copy_from_user(&info, uinfo, info_len))
Daniel Borkmann89b09682017-07-27 21:02:46 +02003615 return -EFAULT;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003616
3617 info.type = prog->type;
3618 info.id = prog->aux->id;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003619 info.load_time = prog->aux->load_time;
3620 info.created_by_uid = from_kuid_munged(current_user_ns(),
3621 prog->aux->user->uid);
Jiri Olsab85fab02018-04-25 19:41:06 +02003622 info.gpl_compatible = prog->gpl_compatible;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003623
3624 memcpy(info.tag, prog->tag, sizeof(prog->tag));
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003625 memcpy(info.name, prog->aux->name, sizeof(prog->aux->name));
3626
YiFei Zhu984fe942020-09-15 16:45:39 -07003627 mutex_lock(&prog->aux->used_maps_mutex);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003628 ulen = info.nr_map_ids;
3629 info.nr_map_ids = prog->aux->used_map_cnt;
3630 ulen = min_t(u32, info.nr_map_ids, ulen);
3631 if (ulen) {
Martin KaFai Lau721e08d2017-09-29 10:52:17 -07003632 u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003633 u32 i;
3634
3635 for (i = 0; i < ulen; i++)
3636 if (put_user(prog->aux->used_maps[i]->id,
YiFei Zhu984fe942020-09-15 16:45:39 -07003637 &user_map_ids[i])) {
3638 mutex_unlock(&prog->aux->used_maps_mutex);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003639 return -EFAULT;
YiFei Zhu984fe942020-09-15 16:45:39 -07003640 }
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003641 }
YiFei Zhu984fe942020-09-15 16:45:39 -07003642 mutex_unlock(&prog->aux->used_maps_mutex);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003643
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003644 err = set_info_rec_size(&info);
3645 if (err)
3646 return err;
Martin KaFai Lau73372242018-12-05 17:35:43 -08003647
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08003648 bpf_prog_get_stats(prog, &stats);
3649 info.run_time_ns = stats.nsecs;
3650 info.run_cnt = stats.cnt;
Alexei Starovoitov9ed9e9b2021-02-09 19:36:31 -08003651 info.recursion_misses = stats.misses;
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08003652
Dave Marchevskyaba64c72021-10-20 00:48:17 -07003653 info.verified_insns = prog->aux->verified_insns;
3654
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07003655 if (!bpf_capable()) {
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003656 info.jited_prog_len = 0;
3657 info.xlated_prog_len = 0;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303658 info.nr_jited_ksyms = 0;
Daniel Borkmann28c2fae2018-11-02 11:35:46 +01003659 info.nr_jited_func_lens = 0;
Yonghong Song11d8b822018-12-10 14:14:08 -08003660 info.nr_func_info = 0;
3661 info.nr_line_info = 0;
3662 info.nr_jited_line_info = 0;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003663 goto done;
3664 }
3665
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003666 ulen = info.xlated_prog_len;
Daniel Borkmann9975a542017-07-28 17:05:25 +02003667 info.xlated_prog_len = bpf_prog_insn_size(prog);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003668 if (info.xlated_prog_len && ulen) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003669 struct bpf_insn *insns_sanitized;
3670 bool fault;
3671
Kees Cook63960262020-07-02 15:45:23 -07003672 if (prog->blinded && !bpf_dump_raw_ok(file->f_cred)) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003673 info.xlated_prog_insns = 0;
3674 goto done;
3675 }
Kees Cook63960262020-07-02 15:45:23 -07003676 insns_sanitized = bpf_insn_prepare_dump(prog, file->f_cred);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003677 if (!insns_sanitized)
3678 return -ENOMEM;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003679 uinsns = u64_to_user_ptr(info.xlated_prog_insns);
3680 ulen = min_t(u32, info.xlated_prog_len, ulen);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003681 fault = copy_to_user(uinsns, insns_sanitized, ulen);
3682 kfree(insns_sanitized);
3683 if (fault)
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003684 return -EFAULT;
3685 }
3686
Jakub Kicinski675fc272017-12-27 18:39:09 -08003687 if (bpf_prog_is_dev_bound(prog->aux)) {
3688 err = bpf_prog_offload_info_fill(&info, prog);
3689 if (err)
3690 return err;
Jiong Wangfcfb1262018-01-16 16:05:19 -08003691 goto done;
3692 }
3693
3694 /* NOTE: the following code is supposed to be skipped for offload.
3695 * bpf_prog_offload_info_fill() is the place to fill similar fields
3696 * for offload.
3697 */
3698 ulen = info.jited_prog_len;
Sandipan Das4d56a762018-05-24 12:26:51 +05303699 if (prog->aux->func_cnt) {
3700 u32 i;
3701
3702 info.jited_prog_len = 0;
3703 for (i = 0; i < prog->aux->func_cnt; i++)
3704 info.jited_prog_len += prog->aux->func[i]->jited_len;
3705 } else {
3706 info.jited_prog_len = prog->jited_len;
3707 }
3708
Jiong Wangfcfb1262018-01-16 16:05:19 -08003709 if (info.jited_prog_len && ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003710 if (bpf_dump_raw_ok(file->f_cred)) {
Jiong Wangfcfb1262018-01-16 16:05:19 -08003711 uinsns = u64_to_user_ptr(info.jited_prog_insns);
3712 ulen = min_t(u32, info.jited_prog_len, ulen);
Sandipan Das4d56a762018-05-24 12:26:51 +05303713
3714 /* for multi-function programs, copy the JITed
3715 * instructions for all the functions
3716 */
3717 if (prog->aux->func_cnt) {
3718 u32 len, free, i;
3719 u8 *img;
3720
3721 free = ulen;
3722 for (i = 0; i < prog->aux->func_cnt; i++) {
3723 len = prog->aux->func[i]->jited_len;
3724 len = min_t(u32, len, free);
3725 img = (u8 *) prog->aux->func[i]->bpf_func;
3726 if (copy_to_user(uinsns, img, len))
3727 return -EFAULT;
3728 uinsns += len;
3729 free -= len;
3730 if (!free)
3731 break;
3732 }
3733 } else {
3734 if (copy_to_user(uinsns, prog->bpf_func, ulen))
3735 return -EFAULT;
3736 }
Jiong Wangfcfb1262018-01-16 16:05:19 -08003737 } else {
3738 info.jited_prog_insns = 0;
3739 }
Jakub Kicinski675fc272017-12-27 18:39:09 -08003740 }
3741
Sandipan Dasdbecd732018-05-24 12:26:48 +05303742 ulen = info.nr_jited_ksyms;
Song Liuff1889f2018-11-02 10:16:17 -07003743 info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08003744 if (ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003745 if (bpf_dump_raw_ok(file->f_cred)) {
Song Liuff1889f2018-11-02 10:16:17 -07003746 unsigned long ksym_addr;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303747 u64 __user *user_ksyms;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303748 u32 i;
3749
3750 /* copy the address of the kernel symbol
3751 * corresponding to each function
3752 */
3753 ulen = min_t(u32, info.nr_jited_ksyms, ulen);
3754 user_ksyms = u64_to_user_ptr(info.jited_ksyms);
Song Liuff1889f2018-11-02 10:16:17 -07003755 if (prog->aux->func_cnt) {
3756 for (i = 0; i < ulen; i++) {
3757 ksym_addr = (unsigned long)
3758 prog->aux->func[i]->bpf_func;
3759 if (put_user((u64) ksym_addr,
3760 &user_ksyms[i]))
3761 return -EFAULT;
3762 }
3763 } else {
3764 ksym_addr = (unsigned long) prog->bpf_func;
3765 if (put_user((u64) ksym_addr, &user_ksyms[0]))
Sandipan Dasdbecd732018-05-24 12:26:48 +05303766 return -EFAULT;
3767 }
3768 } else {
3769 info.jited_ksyms = 0;
3770 }
3771 }
3772
Sandipan Das815581c2018-05-24 12:26:52 +05303773 ulen = info.nr_jited_func_lens;
Song Liuff1889f2018-11-02 10:16:17 -07003774 info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08003775 if (ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003776 if (bpf_dump_raw_ok(file->f_cred)) {
Sandipan Das815581c2018-05-24 12:26:52 +05303777 u32 __user *user_lens;
3778 u32 func_len, i;
3779
3780 /* copy the JITed image lengths for each function */
3781 ulen = min_t(u32, info.nr_jited_func_lens, ulen);
3782 user_lens = u64_to_user_ptr(info.jited_func_lens);
Song Liuff1889f2018-11-02 10:16:17 -07003783 if (prog->aux->func_cnt) {
3784 for (i = 0; i < ulen; i++) {
3785 func_len =
3786 prog->aux->func[i]->jited_len;
3787 if (put_user(func_len, &user_lens[i]))
3788 return -EFAULT;
3789 }
3790 } else {
3791 func_len = prog->jited_len;
3792 if (put_user(func_len, &user_lens[0]))
Sandipan Das815581c2018-05-24 12:26:52 +05303793 return -EFAULT;
3794 }
3795 } else {
3796 info.jited_func_lens = 0;
3797 }
3798 }
3799
Martin KaFai Lau73372242018-12-05 17:35:43 -08003800 if (prog->aux->btf)
Andrii Nakryiko22dc4a02020-12-03 12:46:29 -08003801 info.btf_id = btf_obj_id(prog->aux->btf);
Yonghong Song838e9692018-11-19 15:29:11 -08003802
Yonghong Song11d8b822018-12-10 14:14:08 -08003803 ulen = info.nr_func_info;
3804 info.nr_func_info = prog->aux->func_info_cnt;
3805 if (info.nr_func_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003806 char __user *user_finfo;
Yonghong Song838e9692018-11-19 15:29:11 -08003807
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003808 user_finfo = u64_to_user_ptr(info.func_info);
3809 ulen = min_t(u32, info.nr_func_info, ulen);
3810 if (copy_to_user(user_finfo, prog->aux->func_info,
3811 info.func_info_rec_size * ulen))
3812 return -EFAULT;
Yonghong Song838e9692018-11-19 15:29:11 -08003813 }
3814
Yonghong Song11d8b822018-12-10 14:14:08 -08003815 ulen = info.nr_line_info;
3816 info.nr_line_info = prog->aux->nr_linfo;
3817 if (info.nr_line_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003818 __u8 __user *user_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003819
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003820 user_linfo = u64_to_user_ptr(info.line_info);
3821 ulen = min_t(u32, info.nr_line_info, ulen);
3822 if (copy_to_user(user_linfo, prog->aux->linfo,
3823 info.line_info_rec_size * ulen))
3824 return -EFAULT;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003825 }
3826
Yonghong Song11d8b822018-12-10 14:14:08 -08003827 ulen = info.nr_jited_line_info;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003828 if (prog->aux->jited_linfo)
Yonghong Song11d8b822018-12-10 14:14:08 -08003829 info.nr_jited_line_info = prog->aux->nr_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003830 else
Yonghong Song11d8b822018-12-10 14:14:08 -08003831 info.nr_jited_line_info = 0;
3832 if (info.nr_jited_line_info && ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003833 if (bpf_dump_raw_ok(file->f_cred)) {
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003834 __u64 __user *user_linfo;
3835 u32 i;
3836
3837 user_linfo = u64_to_user_ptr(info.jited_line_info);
Yonghong Song11d8b822018-12-10 14:14:08 -08003838 ulen = min_t(u32, info.nr_jited_line_info, ulen);
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003839 for (i = 0; i < ulen; i++) {
3840 if (put_user((__u64)(long)prog->aux->jited_linfo[i],
3841 &user_linfo[i]))
3842 return -EFAULT;
3843 }
3844 } else {
3845 info.jited_line_info = 0;
3846 }
3847 }
3848
Song Liuc872bdb2018-12-12 09:37:46 -08003849 ulen = info.nr_prog_tags;
3850 info.nr_prog_tags = prog->aux->func_cnt ? : 1;
3851 if (ulen) {
3852 __u8 __user (*user_prog_tags)[BPF_TAG_SIZE];
3853 u32 i;
3854
3855 user_prog_tags = u64_to_user_ptr(info.prog_tags);
3856 ulen = min_t(u32, info.nr_prog_tags, ulen);
3857 if (prog->aux->func_cnt) {
3858 for (i = 0; i < ulen; i++) {
3859 if (copy_to_user(user_prog_tags[i],
3860 prog->aux->func[i]->tag,
3861 BPF_TAG_SIZE))
3862 return -EFAULT;
3863 }
3864 } else {
3865 if (copy_to_user(user_prog_tags[0],
3866 prog->tag, BPF_TAG_SIZE))
3867 return -EFAULT;
3868 }
3869 }
3870
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003871done:
3872 if (copy_to_user(uinfo, &info, info_len) ||
3873 put_user(info_len, &uattr->info.info_len))
3874 return -EFAULT;
3875
3876 return 0;
3877}
3878
Kees Cook63960262020-07-02 15:45:23 -07003879static int bpf_map_get_info_by_fd(struct file *file,
3880 struct bpf_map *map,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003881 const union bpf_attr *attr,
3882 union bpf_attr __user *uattr)
3883{
3884 struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003885 struct bpf_map_info info;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003886 u32 info_len = attr->info.info_len;
3887 int err;
3888
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07003889 err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003890 if (err)
3891 return err;
3892 info_len = min_t(u32, sizeof(info), info_len);
3893
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003894 memset(&info, 0, sizeof(info));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003895 info.type = map->map_type;
3896 info.id = map->id;
3897 info.key_size = map->key_size;
3898 info.value_size = map->value_size;
3899 info.max_entries = map->max_entries;
3900 info.map_flags = map->map_flags;
Joanne Koong93309862021-10-27 16:45:00 -07003901 info.map_extra = map->map_extra;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -07003902 memcpy(info.name, map->name, sizeof(map->name));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003903
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003904 if (map->btf) {
Andrii Nakryiko22dc4a02020-12-03 12:46:29 -08003905 info.btf_id = btf_obj_id(map->btf);
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -07003906 info.btf_key_type_id = map->btf_key_type_id;
3907 info.btf_value_type_id = map->btf_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003908 }
Martin KaFai Lau85d33df2020-01-08 16:35:05 -08003909 info.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003910
Jakub Kicinski52775b32018-01-17 19:13:28 -08003911 if (bpf_map_is_dev_bound(map)) {
3912 err = bpf_map_offload_info_fill(&info, map);
3913 if (err)
3914 return err;
3915 }
3916
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003917 if (copy_to_user(uinfo, &info, info_len) ||
3918 put_user(info_len, &uattr->info.info_len))
3919 return -EFAULT;
3920
3921 return 0;
3922}
3923
Kees Cook63960262020-07-02 15:45:23 -07003924static int bpf_btf_get_info_by_fd(struct file *file,
3925 struct btf *btf,
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003926 const union bpf_attr *attr,
3927 union bpf_attr __user *uattr)
3928{
3929 struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info);
3930 u32 info_len = attr->info.info_len;
3931 int err;
3932
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07003933 err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(*uinfo), info_len);
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003934 if (err)
3935 return err;
3936
3937 return btf_get_info_by_fd(btf, attr, uattr);
3938}
3939
Kees Cook63960262020-07-02 15:45:23 -07003940static int bpf_link_get_info_by_fd(struct file *file,
3941 struct bpf_link *link,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003942 const union bpf_attr *attr,
3943 union bpf_attr __user *uattr)
3944{
3945 struct bpf_link_info __user *uinfo = u64_to_user_ptr(attr->info.info);
3946 struct bpf_link_info info;
3947 u32 info_len = attr->info.info_len;
3948 int err;
3949
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07003950 err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003951 if (err)
3952 return err;
3953 info_len = min_t(u32, sizeof(info), info_len);
3954
3955 memset(&info, 0, sizeof(info));
3956 if (copy_from_user(&info, uinfo, info_len))
3957 return -EFAULT;
3958
3959 info.type = link->type;
3960 info.id = link->id;
3961 info.prog_id = link->prog->aux->id;
3962
3963 if (link->ops->fill_link_info) {
3964 err = link->ops->fill_link_info(link, &info);
3965 if (err)
3966 return err;
3967 }
3968
3969 if (copy_to_user(uinfo, &info, info_len) ||
3970 put_user(info_len, &uattr->info.info_len))
3971 return -EFAULT;
3972
3973 return 0;
3974}
3975
3976
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003977#define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info
3978
3979static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
3980 union bpf_attr __user *uattr)
3981{
3982 int ufd = attr->info.bpf_fd;
3983 struct fd f;
3984 int err;
3985
3986 if (CHECK_ATTR(BPF_OBJ_GET_INFO_BY_FD))
3987 return -EINVAL;
3988
3989 f = fdget(ufd);
3990 if (!f.file)
3991 return -EBADFD;
3992
3993 if (f.file->f_op == &bpf_prog_fops)
Kees Cook63960262020-07-02 15:45:23 -07003994 err = bpf_prog_get_info_by_fd(f.file, f.file->private_data, attr,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003995 uattr);
3996 else if (f.file->f_op == &bpf_map_fops)
Kees Cook63960262020-07-02 15:45:23 -07003997 err = bpf_map_get_info_by_fd(f.file, f.file->private_data, attr,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003998 uattr);
Martin KaFai Lau60197cf2018-04-18 15:56:02 -07003999 else if (f.file->f_op == &btf_fops)
Kees Cook63960262020-07-02 15:45:23 -07004000 err = bpf_btf_get_info_by_fd(f.file, f.file->private_data, attr, uattr);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07004001 else if (f.file->f_op == &bpf_link_fops)
Kees Cook63960262020-07-02 15:45:23 -07004002 err = bpf_link_get_info_by_fd(f.file, f.file->private_data,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07004003 attr, uattr);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004004 else
4005 err = -EINVAL;
4006
4007 fdput(f);
4008 return err;
4009}
4010
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004011#define BPF_BTF_LOAD_LAST_FIELD btf_log_level
4012
Alexei Starovoitovc571bd72021-05-13 17:36:08 -07004013static int bpf_btf_load(const union bpf_attr *attr, bpfptr_t uattr)
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004014{
4015 if (CHECK_ATTR(BPF_BTF_LOAD))
4016 return -EINVAL;
4017
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07004018 if (!bpf_capable())
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004019 return -EPERM;
4020
Alexei Starovoitovc571bd72021-05-13 17:36:08 -07004021 return btf_new_fd(attr, uattr);
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004022}
4023
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07004024#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id
4025
4026static int bpf_btf_get_fd_by_id(const union bpf_attr *attr)
4027{
4028 if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID))
4029 return -EINVAL;
4030
4031 if (!capable(CAP_SYS_ADMIN))
4032 return -EPERM;
4033
4034 return btf_get_fd_by_id(attr->btf_id);
4035}
4036
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004037static int bpf_task_fd_query_copy(const union bpf_attr *attr,
4038 union bpf_attr __user *uattr,
4039 u32 prog_id, u32 fd_type,
4040 const char *buf, u64 probe_offset,
4041 u64 probe_addr)
4042{
4043 char __user *ubuf = u64_to_user_ptr(attr->task_fd_query.buf);
4044 u32 len = buf ? strlen(buf) : 0, input_len;
4045 int err = 0;
4046
4047 if (put_user(len, &uattr->task_fd_query.buf_len))
4048 return -EFAULT;
4049 input_len = attr->task_fd_query.buf_len;
4050 if (input_len && ubuf) {
4051 if (!len) {
4052 /* nothing to copy, just make ubuf NULL terminated */
4053 char zero = '\0';
4054
4055 if (put_user(zero, ubuf))
4056 return -EFAULT;
4057 } else if (input_len >= len + 1) {
4058 /* ubuf can hold the string with NULL terminator */
4059 if (copy_to_user(ubuf, buf, len + 1))
4060 return -EFAULT;
4061 } else {
4062 /* ubuf cannot hold the string with NULL terminator,
4063 * do a partial copy with NULL terminator.
4064 */
4065 char zero = '\0';
4066
4067 err = -ENOSPC;
4068 if (copy_to_user(ubuf, buf, input_len - 1))
4069 return -EFAULT;
4070 if (put_user(zero, ubuf + input_len - 1))
4071 return -EFAULT;
4072 }
4073 }
4074
4075 if (put_user(prog_id, &uattr->task_fd_query.prog_id) ||
4076 put_user(fd_type, &uattr->task_fd_query.fd_type) ||
4077 put_user(probe_offset, &uattr->task_fd_query.probe_offset) ||
4078 put_user(probe_addr, &uattr->task_fd_query.probe_addr))
4079 return -EFAULT;
4080
4081 return err;
4082}
4083
4084#define BPF_TASK_FD_QUERY_LAST_FIELD task_fd_query.probe_addr
4085
4086static int bpf_task_fd_query(const union bpf_attr *attr,
4087 union bpf_attr __user *uattr)
4088{
4089 pid_t pid = attr->task_fd_query.pid;
4090 u32 fd = attr->task_fd_query.fd;
4091 const struct perf_event *event;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004092 struct task_struct *task;
4093 struct file *file;
4094 int err;
4095
4096 if (CHECK_ATTR(BPF_TASK_FD_QUERY))
4097 return -EINVAL;
4098
4099 if (!capable(CAP_SYS_ADMIN))
4100 return -EPERM;
4101
4102 if (attr->task_fd_query.flags != 0)
4103 return -EINVAL;
4104
4105 task = get_pid_task(find_vpid(pid), PIDTYPE_PID);
4106 if (!task)
4107 return -ENOENT;
4108
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004109 err = 0;
Eric W. Biedermanb48845a2020-11-20 17:14:22 -06004110 file = fget_task(task, fd);
4111 put_task_struct(task);
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004112 if (!file)
Eric W. Biedermanb48845a2020-11-20 17:14:22 -06004113 return -EBADF;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004114
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08004115 if (file->f_op == &bpf_link_fops) {
4116 struct bpf_link *link = file->private_data;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004117
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07004118 if (link->ops == &bpf_raw_tp_link_lops) {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08004119 struct bpf_raw_tp_link *raw_tp =
4120 container_of(link, struct bpf_raw_tp_link, link);
4121 struct bpf_raw_event_map *btp = raw_tp->btp;
4122
4123 err = bpf_task_fd_query_copy(attr, uattr,
4124 raw_tp->link.prog->aux->id,
4125 BPF_FD_TYPE_RAW_TRACEPOINT,
4126 btp->tp->name, 0, 0);
4127 goto put_file;
4128 }
4129 goto out_not_supp;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004130 }
4131
4132 event = perf_get_event(file);
4133 if (!IS_ERR(event)) {
4134 u64 probe_offset, probe_addr;
4135 u32 prog_id, fd_type;
4136 const char *buf;
4137
4138 err = bpf_get_perf_event_info(event, &prog_id, &fd_type,
4139 &buf, &probe_offset,
4140 &probe_addr);
4141 if (!err)
4142 err = bpf_task_fd_query_copy(attr, uattr, prog_id,
4143 fd_type, buf,
4144 probe_offset,
4145 probe_addr);
4146 goto put_file;
4147 }
4148
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08004149out_not_supp:
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004150 err = -ENOTSUPP;
4151put_file:
4152 fput(file);
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004153 return err;
4154}
4155
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004156#define BPF_MAP_BATCH_LAST_FIELD batch.flags
4157
4158#define BPF_DO_BATCH(fn) \
4159 do { \
4160 if (!fn) { \
4161 err = -ENOTSUPP; \
4162 goto err_put; \
4163 } \
4164 err = fn(map, attr, uattr); \
4165 } while (0)
4166
4167static int bpf_map_do_batch(const union bpf_attr *attr,
4168 union bpf_attr __user *uattr,
4169 int cmd)
4170{
4171 struct bpf_map *map;
4172 int err, ufd;
4173 struct fd f;
4174
4175 if (CHECK_ATTR(BPF_MAP_BATCH))
4176 return -EINVAL;
4177
4178 ufd = attr->batch.map_fd;
4179 f = fdget(ufd);
4180 map = __bpf_map_get(f);
4181 if (IS_ERR(map))
4182 return PTR_ERR(map);
4183
Yonghong Song05799632020-01-15 10:43:04 -08004184 if ((cmd == BPF_MAP_LOOKUP_BATCH ||
4185 cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH) &&
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004186 !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
4187 err = -EPERM;
4188 goto err_put;
4189 }
4190
4191 if (cmd != BPF_MAP_LOOKUP_BATCH &&
4192 !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
4193 err = -EPERM;
4194 goto err_put;
4195 }
4196
4197 if (cmd == BPF_MAP_LOOKUP_BATCH)
4198 BPF_DO_BATCH(map->ops->map_lookup_batch);
Yonghong Song05799632020-01-15 10:43:04 -08004199 else if (cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH)
4200 BPF_DO_BATCH(map->ops->map_lookup_and_delete_batch);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004201 else if (cmd == BPF_MAP_UPDATE_BATCH)
4202 BPF_DO_BATCH(map->ops->map_update_batch);
4203 else
4204 BPF_DO_BATCH(map->ops->map_delete_batch);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004205
4206err_put:
4207 fdput(f);
4208 return err;
4209}
4210
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004211static int tracing_bpf_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
4212 struct bpf_prog *prog)
Yonghong Songde4e05c2020-05-09 10:59:01 -07004213{
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004214 if (attr->link_create.attach_type != prog->expected_attach_type)
4215 return -EINVAL;
Yonghong Songde4e05c2020-05-09 10:59:01 -07004216
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004217 if (prog->expected_attach_type == BPF_TRACE_ITER)
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004218 return bpf_iter_link_attach(attr, uattr, prog);
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004219 else if (prog->type == BPF_PROG_TYPE_EXT)
4220 return bpf_tracing_prog_attach(prog,
4221 attr->link_create.target_fd,
4222 attr->link_create.target_btf_id);
Yonghong Songde4e05c2020-05-09 10:59:01 -07004223 return -EINVAL;
4224}
4225
Yonghong Song5e7b3022020-08-04 22:50:56 -07004226#define BPF_LINK_CREATE_LAST_FIELD link_create.iter_info_len
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004227static int link_create(union bpf_attr *attr, bpfptr_t uattr)
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004228{
4229 enum bpf_prog_type ptype;
4230 struct bpf_prog *prog;
4231 int ret;
4232
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004233 if (CHECK_ATTR(BPF_LINK_CREATE))
4234 return -EINVAL;
4235
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004236 prog = bpf_prog_get(attr->link_create.prog_fd);
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004237 if (IS_ERR(prog))
4238 return PTR_ERR(prog);
4239
4240 ret = bpf_prog_attach_check_attach_type(prog,
4241 attr->link_create.attach_type);
4242 if (ret)
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004243 goto out;
4244
Andrii Nakryikob89fbfb2021-08-15 00:05:57 -07004245 switch (prog->type) {
4246 case BPF_PROG_TYPE_EXT:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004247 ret = tracing_bpf_link_attach(attr, uattr, prog);
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004248 goto out;
Andrii Nakryikob89fbfb2021-08-15 00:05:57 -07004249 case BPF_PROG_TYPE_PERF_EVENT:
4250 case BPF_PROG_TYPE_KPROBE:
4251 case BPF_PROG_TYPE_TRACEPOINT:
4252 if (attr->link_create.attach_type != BPF_PERF_EVENT) {
4253 ret = -EINVAL;
4254 goto out;
4255 }
4256 ptype = prog->type;
4257 break;
4258 default:
4259 ptype = attach_type_to_prog_type(attr->link_create.attach_type);
4260 if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type) {
4261 ret = -EINVAL;
4262 goto out;
4263 }
4264 break;
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004265 }
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004266
4267 switch (ptype) {
4268 case BPF_PROG_TYPE_CGROUP_SKB:
4269 case BPF_PROG_TYPE_CGROUP_SOCK:
4270 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
4271 case BPF_PROG_TYPE_SOCK_OPS:
4272 case BPF_PROG_TYPE_CGROUP_DEVICE:
4273 case BPF_PROG_TYPE_CGROUP_SYSCTL:
4274 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
4275 ret = cgroup_bpf_link_attach(attr, prog);
4276 break;
Yonghong Songde4e05c2020-05-09 10:59:01 -07004277 case BPF_PROG_TYPE_TRACING:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004278 ret = tracing_bpf_link_attach(attr, uattr, prog);
Yonghong Songde4e05c2020-05-09 10:59:01 -07004279 break;
Jakub Sitnicki7f045a42020-05-31 10:28:38 +02004280 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02004281 case BPF_PROG_TYPE_SK_LOOKUP:
Jakub Sitnicki7f045a42020-05-31 10:28:38 +02004282 ret = netns_bpf_link_create(attr, prog);
4283 break;
Andrii Nakryiko310ad792020-07-28 12:05:27 -07004284#ifdef CONFIG_NET
Andrii Nakryikoaa8d3a72020-07-21 23:45:57 -07004285 case BPF_PROG_TYPE_XDP:
4286 ret = bpf_xdp_link_attach(attr, prog);
4287 break;
Andrii Nakryiko310ad792020-07-28 12:05:27 -07004288#endif
Andrii Nakryikob89fbfb2021-08-15 00:05:57 -07004289#ifdef CONFIG_PERF_EVENTS
4290 case BPF_PROG_TYPE_PERF_EVENT:
4291 case BPF_PROG_TYPE_TRACEPOINT:
4292 case BPF_PROG_TYPE_KPROBE:
4293 ret = bpf_perf_link_attach(attr, prog);
4294 break;
4295#endif
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004296 default:
4297 ret = -EINVAL;
4298 }
4299
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004300out:
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004301 if (ret < 0)
4302 bpf_prog_put(prog);
4303 return ret;
4304}
4305
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004306#define BPF_LINK_UPDATE_LAST_FIELD link_update.old_prog_fd
4307
4308static int link_update(union bpf_attr *attr)
4309{
4310 struct bpf_prog *old_prog = NULL, *new_prog;
4311 struct bpf_link *link;
4312 u32 flags;
4313 int ret;
4314
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004315 if (CHECK_ATTR(BPF_LINK_UPDATE))
4316 return -EINVAL;
4317
4318 flags = attr->link_update.flags;
4319 if (flags & ~BPF_F_REPLACE)
4320 return -EINVAL;
4321
4322 link = bpf_link_get_from_fd(attr->link_update.link_fd);
4323 if (IS_ERR(link))
4324 return PTR_ERR(link);
4325
4326 new_prog = bpf_prog_get(attr->link_update.new_prog_fd);
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07004327 if (IS_ERR(new_prog)) {
4328 ret = PTR_ERR(new_prog);
4329 goto out_put_link;
4330 }
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004331
4332 if (flags & BPF_F_REPLACE) {
4333 old_prog = bpf_prog_get(attr->link_update.old_prog_fd);
4334 if (IS_ERR(old_prog)) {
4335 ret = PTR_ERR(old_prog);
4336 old_prog = NULL;
4337 goto out_put_progs;
4338 }
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07004339 } else if (attr->link_update.old_prog_fd) {
4340 ret = -EINVAL;
4341 goto out_put_progs;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004342 }
4343
Andrii Nakryikof9d04122020-04-28 17:16:05 -07004344 if (link->ops->update_prog)
4345 ret = link->ops->update_prog(link, new_prog, old_prog);
4346 else
Jakub Sitnickife537392020-05-25 14:29:28 +02004347 ret = -EINVAL;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004348
4349out_put_progs:
4350 if (old_prog)
4351 bpf_prog_put(old_prog);
4352 if (ret)
4353 bpf_prog_put(new_prog);
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07004354out_put_link:
4355 bpf_link_put(link);
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004356 return ret;
4357}
4358
Andrii Nakryiko73b11c2a2020-07-31 11:28:26 -07004359#define BPF_LINK_DETACH_LAST_FIELD link_detach.link_fd
4360
4361static int link_detach(union bpf_attr *attr)
4362{
4363 struct bpf_link *link;
4364 int ret;
4365
4366 if (CHECK_ATTR(BPF_LINK_DETACH))
4367 return -EINVAL;
4368
4369 link = bpf_link_get_from_fd(attr->link_detach.link_fd);
4370 if (IS_ERR(link))
4371 return PTR_ERR(link);
4372
4373 if (link->ops->detach)
4374 ret = link->ops->detach(link);
4375 else
4376 ret = -EOPNOTSUPP;
4377
4378 bpf_link_put(link);
4379 return ret;
4380}
4381
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004382static struct bpf_link *bpf_link_inc_not_zero(struct bpf_link *link)
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004383{
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004384 return atomic64_fetch_add_unless(&link->refcnt, 1, 0) ? link : ERR_PTR(-ENOENT);
4385}
4386
4387struct bpf_link *bpf_link_by_id(u32 id)
4388{
4389 struct bpf_link *link;
4390
4391 if (!id)
4392 return ERR_PTR(-ENOENT);
4393
4394 spin_lock_bh(&link_idr_lock);
4395 /* before link is "settled", ID is 0, pretend it doesn't exist yet */
4396 link = idr_find(&link_idr, id);
4397 if (link) {
4398 if (link->id)
4399 link = bpf_link_inc_not_zero(link);
4400 else
4401 link = ERR_PTR(-EAGAIN);
4402 } else {
4403 link = ERR_PTR(-ENOENT);
4404 }
4405 spin_unlock_bh(&link_idr_lock);
4406 return link;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004407}
4408
4409#define BPF_LINK_GET_FD_BY_ID_LAST_FIELD link_id
4410
4411static int bpf_link_get_fd_by_id(const union bpf_attr *attr)
4412{
4413 struct bpf_link *link;
4414 u32 id = attr->link_id;
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004415 int fd;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004416
4417 if (CHECK_ATTR(BPF_LINK_GET_FD_BY_ID))
4418 return -EINVAL;
4419
4420 if (!capable(CAP_SYS_ADMIN))
4421 return -EPERM;
4422
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004423 link = bpf_link_by_id(id);
4424 if (IS_ERR(link))
4425 return PTR_ERR(link);
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004426
4427 fd = bpf_link_new_fd(link);
4428 if (fd < 0)
4429 bpf_link_put(link);
4430
4431 return fd;
4432}
4433
Song Liud46edd62020-04-30 00:15:04 -07004434DEFINE_MUTEX(bpf_stats_enabled_mutex);
4435
4436static int bpf_stats_release(struct inode *inode, struct file *file)
4437{
4438 mutex_lock(&bpf_stats_enabled_mutex);
4439 static_key_slow_dec(&bpf_stats_enabled_key.key);
4440 mutex_unlock(&bpf_stats_enabled_mutex);
4441 return 0;
4442}
4443
4444static const struct file_operations bpf_stats_fops = {
4445 .release = bpf_stats_release,
4446};
4447
4448static int bpf_enable_runtime_stats(void)
4449{
4450 int fd;
4451
4452 mutex_lock(&bpf_stats_enabled_mutex);
4453
4454 /* Set a very high limit to avoid overflow */
4455 if (static_key_count(&bpf_stats_enabled_key.key) > INT_MAX / 2) {
4456 mutex_unlock(&bpf_stats_enabled_mutex);
4457 return -EBUSY;
4458 }
4459
4460 fd = anon_inode_getfd("bpf-stats", &bpf_stats_fops, NULL, O_CLOEXEC);
4461 if (fd >= 0)
4462 static_key_slow_inc(&bpf_stats_enabled_key.key);
4463
4464 mutex_unlock(&bpf_stats_enabled_mutex);
4465 return fd;
4466}
4467
4468#define BPF_ENABLE_STATS_LAST_FIELD enable_stats.type
4469
4470static int bpf_enable_stats(union bpf_attr *attr)
4471{
4472
4473 if (CHECK_ATTR(BPF_ENABLE_STATS))
4474 return -EINVAL;
4475
4476 if (!capable(CAP_SYS_ADMIN))
4477 return -EPERM;
4478
4479 switch (attr->enable_stats.type) {
4480 case BPF_STATS_RUN_TIME:
4481 return bpf_enable_runtime_stats();
4482 default:
4483 break;
4484 }
4485 return -EINVAL;
4486}
4487
Yonghong Songac51d992020-05-09 10:59:05 -07004488#define BPF_ITER_CREATE_LAST_FIELD iter_create.flags
4489
4490static int bpf_iter_create(union bpf_attr *attr)
4491{
4492 struct bpf_link *link;
4493 int err;
4494
4495 if (CHECK_ATTR(BPF_ITER_CREATE))
4496 return -EINVAL;
4497
4498 if (attr->iter_create.flags)
4499 return -EINVAL;
4500
4501 link = bpf_link_get_from_fd(attr->iter_create.link_fd);
4502 if (IS_ERR(link))
4503 return PTR_ERR(link);
4504
4505 err = bpf_iter_new_fd(link);
4506 bpf_link_put(link);
4507
4508 return err;
4509}
4510
YiFei Zhuef153142020-09-15 16:45:40 -07004511#define BPF_PROG_BIND_MAP_LAST_FIELD prog_bind_map.flags
4512
4513static int bpf_prog_bind_map(union bpf_attr *attr)
4514{
4515 struct bpf_prog *prog;
4516 struct bpf_map *map;
4517 struct bpf_map **used_maps_old, **used_maps_new;
4518 int i, ret = 0;
4519
4520 if (CHECK_ATTR(BPF_PROG_BIND_MAP))
4521 return -EINVAL;
4522
4523 if (attr->prog_bind_map.flags)
4524 return -EINVAL;
4525
4526 prog = bpf_prog_get(attr->prog_bind_map.prog_fd);
4527 if (IS_ERR(prog))
4528 return PTR_ERR(prog);
4529
4530 map = bpf_map_get(attr->prog_bind_map.map_fd);
4531 if (IS_ERR(map)) {
4532 ret = PTR_ERR(map);
4533 goto out_prog_put;
4534 }
4535
4536 mutex_lock(&prog->aux->used_maps_mutex);
4537
4538 used_maps_old = prog->aux->used_maps;
4539
4540 for (i = 0; i < prog->aux->used_map_cnt; i++)
Stanislav Fomichev1028ae42020-10-02 17:25:44 -07004541 if (used_maps_old[i] == map) {
4542 bpf_map_put(map);
YiFei Zhuef153142020-09-15 16:45:40 -07004543 goto out_unlock;
Stanislav Fomichev1028ae42020-10-02 17:25:44 -07004544 }
YiFei Zhuef153142020-09-15 16:45:40 -07004545
4546 used_maps_new = kmalloc_array(prog->aux->used_map_cnt + 1,
4547 sizeof(used_maps_new[0]),
4548 GFP_KERNEL);
4549 if (!used_maps_new) {
4550 ret = -ENOMEM;
4551 goto out_unlock;
4552 }
4553
4554 memcpy(used_maps_new, used_maps_old,
4555 sizeof(used_maps_old[0]) * prog->aux->used_map_cnt);
4556 used_maps_new[prog->aux->used_map_cnt] = map;
4557
4558 prog->aux->used_map_cnt++;
4559 prog->aux->used_maps = used_maps_new;
4560
4561 kfree(used_maps_old);
4562
4563out_unlock:
4564 mutex_unlock(&prog->aux->used_maps_mutex);
4565
4566 if (ret)
4567 bpf_map_put(map);
4568out_prog_put:
4569 bpf_prog_put(prog);
4570 return ret;
4571}
4572
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004573static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004574{
Greg Kroah-Hartman8096f222020-03-20 10:48:13 +01004575 union bpf_attr attr;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004576 int err;
4577
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07004578 if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004579 return -EPERM;
4580
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07004581 err = bpf_check_uarg_tail_zero(uattr, sizeof(attr), size);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004582 if (err)
4583 return err;
4584 size = min_t(u32, size, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004585
4586 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
Greg Kroah-Hartman8096f222020-03-20 10:48:13 +01004587 memset(&attr, 0, sizeof(attr));
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004588 if (copy_from_bpfptr(&attr, uattr, size) != 0)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004589 return -EFAULT;
4590
Chenbo Fengafdb09c2017-10-18 13:00:24 -07004591 err = security_bpf(cmd, &attr, size);
4592 if (err < 0)
4593 return err;
4594
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004595 switch (cmd) {
4596 case BPF_MAP_CREATE:
4597 err = map_create(&attr);
4598 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07004599 case BPF_MAP_LOOKUP_ELEM:
4600 err = map_lookup_elem(&attr);
4601 break;
4602 case BPF_MAP_UPDATE_ELEM:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004603 err = map_update_elem(&attr, uattr);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07004604 break;
4605 case BPF_MAP_DELETE_ELEM:
4606 err = map_delete_elem(&attr);
4607 break;
4608 case BPF_MAP_GET_NEXT_KEY:
4609 err = map_get_next_key(&attr);
4610 break;
Daniel Borkmann87df15d2019-04-09 23:20:06 +02004611 case BPF_MAP_FREEZE:
4612 err = map_freeze(&attr);
4613 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07004614 case BPF_PROG_LOAD:
Yonghong Song838e9692018-11-19 15:29:11 -08004615 err = bpf_prog_load(&attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07004616 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01004617 case BPF_OBJ_PIN:
4618 err = bpf_obj_pin(&attr);
4619 break;
4620 case BPF_OBJ_GET:
4621 err = bpf_obj_get(&attr);
4622 break;
Daniel Mackf4324552016-11-23 16:52:27 +01004623 case BPF_PROG_ATTACH:
4624 err = bpf_prog_attach(&attr);
4625 break;
4626 case BPF_PROG_DETACH:
4627 err = bpf_prog_detach(&attr);
4628 break;
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07004629 case BPF_PROG_QUERY:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004630 err = bpf_prog_query(&attr, uattr.user);
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07004631 break;
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07004632 case BPF_PROG_TEST_RUN:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004633 err = bpf_prog_test_run(&attr, uattr.user);
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07004634 break;
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07004635 case BPF_PROG_GET_NEXT_ID:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004636 err = bpf_obj_get_next_id(&attr, uattr.user,
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07004637 &prog_idr, &prog_idr_lock);
4638 break;
4639 case BPF_MAP_GET_NEXT_ID:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004640 err = bpf_obj_get_next_id(&attr, uattr.user,
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07004641 &map_idr, &map_idr_lock);
4642 break;
Quentin Monnet1b9ed842019-08-20 10:31:50 +01004643 case BPF_BTF_GET_NEXT_ID:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004644 err = bpf_obj_get_next_id(&attr, uattr.user,
Quentin Monnet1b9ed842019-08-20 10:31:50 +01004645 &btf_idr, &btf_idr_lock);
4646 break;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07004647 case BPF_PROG_GET_FD_BY_ID:
4648 err = bpf_prog_get_fd_by_id(&attr);
4649 break;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07004650 case BPF_MAP_GET_FD_BY_ID:
4651 err = bpf_map_get_fd_by_id(&attr);
4652 break;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004653 case BPF_OBJ_GET_INFO_BY_FD:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004654 err = bpf_obj_get_info_by_fd(&attr, uattr.user);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004655 break;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07004656 case BPF_RAW_TRACEPOINT_OPEN:
4657 err = bpf_raw_tracepoint_open(&attr);
4658 break;
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004659 case BPF_BTF_LOAD:
Alexei Starovoitovc571bd72021-05-13 17:36:08 -07004660 err = bpf_btf_load(&attr, uattr);
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004661 break;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07004662 case BPF_BTF_GET_FD_BY_ID:
4663 err = bpf_btf_get_fd_by_id(&attr);
4664 break;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004665 case BPF_TASK_FD_QUERY:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004666 err = bpf_task_fd_query(&attr, uattr.user);
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004667 break;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02004668 case BPF_MAP_LOOKUP_AND_DELETE_ELEM:
4669 err = map_lookup_and_delete_elem(&attr);
4670 break;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004671 case BPF_MAP_LOOKUP_BATCH:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004672 err = bpf_map_do_batch(&attr, uattr.user, BPF_MAP_LOOKUP_BATCH);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004673 break;
Yonghong Song05799632020-01-15 10:43:04 -08004674 case BPF_MAP_LOOKUP_AND_DELETE_BATCH:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004675 err = bpf_map_do_batch(&attr, uattr.user,
Yonghong Song05799632020-01-15 10:43:04 -08004676 BPF_MAP_LOOKUP_AND_DELETE_BATCH);
4677 break;
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004678 case BPF_MAP_UPDATE_BATCH:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004679 err = bpf_map_do_batch(&attr, uattr.user, BPF_MAP_UPDATE_BATCH);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004680 break;
4681 case BPF_MAP_DELETE_BATCH:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004682 err = bpf_map_do_batch(&attr, uattr.user, BPF_MAP_DELETE_BATCH);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004683 break;
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004684 case BPF_LINK_CREATE:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004685 err = link_create(&attr, uattr);
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004686 break;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004687 case BPF_LINK_UPDATE:
4688 err = link_update(&attr);
4689 break;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004690 case BPF_LINK_GET_FD_BY_ID:
4691 err = bpf_link_get_fd_by_id(&attr);
4692 break;
4693 case BPF_LINK_GET_NEXT_ID:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004694 err = bpf_obj_get_next_id(&attr, uattr.user,
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004695 &link_idr, &link_idr_lock);
4696 break;
Song Liud46edd62020-04-30 00:15:04 -07004697 case BPF_ENABLE_STATS:
4698 err = bpf_enable_stats(&attr);
4699 break;
Yonghong Songac51d992020-05-09 10:59:05 -07004700 case BPF_ITER_CREATE:
4701 err = bpf_iter_create(&attr);
4702 break;
Andrii Nakryiko73b11c2a2020-07-31 11:28:26 -07004703 case BPF_LINK_DETACH:
4704 err = link_detach(&attr);
4705 break;
YiFei Zhuef153142020-09-15 16:45:40 -07004706 case BPF_PROG_BIND_MAP:
4707 err = bpf_prog_bind_map(&attr);
4708 break;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004709 default:
4710 err = -EINVAL;
4711 break;
4712 }
4713
4714 return err;
4715}
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07004716
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004717SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
4718{
4719 return __sys_bpf(cmd, USER_BPFPTR(uattr), size);
4720}
4721
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07004722static bool syscall_prog_is_valid_access(int off, int size,
4723 enum bpf_access_type type,
4724 const struct bpf_prog *prog,
4725 struct bpf_insn_access_aux *info)
4726{
4727 if (off < 0 || off >= U16_MAX)
4728 return false;
4729 if (off % size != 0)
4730 return false;
4731 return true;
4732}
4733
4734BPF_CALL_3(bpf_sys_bpf, int, cmd, void *, attr, u32, attr_size)
4735{
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004736 switch (cmd) {
4737 case BPF_MAP_CREATE:
4738 case BPF_MAP_UPDATE_ELEM:
4739 case BPF_MAP_FREEZE:
4740 case BPF_PROG_LOAD:
Alexei Starovoitovc571bd72021-05-13 17:36:08 -07004741 case BPF_BTF_LOAD:
Alexei Starovoitovaf2ac3e2021-05-13 17:36:05 -07004742 break;
4743 /* case BPF_PROG_TEST_RUN:
4744 * is not part of this list to prevent recursive test_run
4745 */
4746 default:
4747 return -EINVAL;
4748 }
4749 return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size);
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07004750}
4751
Pu Lehui3a2daa72021-05-19 14:41:16 +08004752static const struct bpf_func_proto bpf_sys_bpf_proto = {
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07004753 .func = bpf_sys_bpf,
4754 .gpl_only = false,
4755 .ret_type = RET_INTEGER,
4756 .arg1_type = ARG_ANYTHING,
4757 .arg2_type = ARG_PTR_TO_MEM,
4758 .arg3_type = ARG_CONST_SIZE,
4759};
4760
4761const struct bpf_func_proto * __weak
4762tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
4763{
4764 return bpf_base_func_proto(func_id);
4765}
4766
Alexei Starovoitov3abea082021-05-13 17:36:12 -07004767BPF_CALL_1(bpf_sys_close, u32, fd)
4768{
4769 /* When bpf program calls this helper there should not be
4770 * an fdget() without matching completed fdput().
4771 * This helper is allowed in the following callchain only:
4772 * sys_bpf->prog_test_run->bpf_prog->bpf_sys_close
4773 */
4774 return close_fd(fd);
4775}
4776
Pu Lehui3a2daa72021-05-19 14:41:16 +08004777static const struct bpf_func_proto bpf_sys_close_proto = {
Alexei Starovoitov3abea082021-05-13 17:36:12 -07004778 .func = bpf_sys_close,
4779 .gpl_only = false,
4780 .ret_type = RET_INTEGER,
4781 .arg1_type = ARG_ANYTHING,
4782};
4783
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07004784static const struct bpf_func_proto *
4785syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
4786{
4787 switch (func_id) {
4788 case BPF_FUNC_sys_bpf:
4789 return &bpf_sys_bpf_proto;
Alexei Starovoitov3d784172021-05-13 17:36:11 -07004790 case BPF_FUNC_btf_find_by_name_kind:
4791 return &bpf_btf_find_by_name_kind_proto;
Alexei Starovoitov3abea082021-05-13 17:36:12 -07004792 case BPF_FUNC_sys_close:
4793 return &bpf_sys_close_proto;
Alexei Starovoitov79a7f8b2021-05-13 17:36:03 -07004794 default:
4795 return tracing_prog_func_proto(func_id, prog);
4796 }
4797}
4798
4799const struct bpf_verifier_ops bpf_syscall_verifier_ops = {
4800 .get_func_proto = syscall_prog_func_proto,
4801 .is_valid_access = syscall_prog_is_valid_access,
4802};
4803
4804const struct bpf_prog_ops bpf_syscall_prog_ops = {
4805 .test_run = bpf_prog_test_run_syscall,
4806};