blob: dedbf6d4cd8400d5d59fbec1c9d9ef00c4686fa4 [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>
Alexei Starovoitov25415172015-03-25 12:49:20 -070020#include <linux/version.h>
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +010021#include <linux/kernel.h>
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070022#include <linux/idr.h>
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -070023#include <linux/cred.h>
24#include <linux/timekeeping.h>
25#include <linux/ctype.h>
Mark Rutland9ef09e32018-05-03 17:04:59 +010026#include <linux/nospec.h>
Daniel Borkmannbae141f2019-12-06 22:49:34 +010027#include <linux/audit.h>
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -070028#include <uapi/linux/btf.h>
Mike Rapoportca5999f2020-06-08 21:32:38 -070029#include <linux/pgtable.h>
KP Singh9e4e01d2020-03-29 01:43:52 +010030#include <linux/bpf_lsm.h>
Andrii Nakryiko457f4432020-05-29 00:54:20 -070031#include <linux/poll.h>
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +020032#include <linux/bpf-netns.h>
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -070033#include <linux/rcupdate_trace.h>
Roman Gushchin48edc1f2020-12-01 13:58:32 -080034#include <linux/memcontrol.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070035
Daniel Borkmannda765a22019-11-22 21:07:58 +010036#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
37 (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
38 (map)->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
39#define IS_FD_PROG_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY)
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070040#define IS_FD_HASH(map) ((map)->map_type == BPF_MAP_TYPE_HASH_OF_MAPS)
Daniel Borkmannda765a22019-11-22 21:07:58 +010041#define IS_FD_MAP(map) (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map) || \
42 IS_FD_HASH(map))
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070043
Chenbo Feng6e71b042017-10-18 13:00:22 -070044#define BPF_OBJ_FLAG_MASK (BPF_F_RDONLY | BPF_F_WRONLY)
45
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080046DEFINE_PER_CPU(int, bpf_prog_active);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070047static DEFINE_IDR(prog_idr);
48static DEFINE_SPINLOCK(prog_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -070049static DEFINE_IDR(map_idr);
50static DEFINE_SPINLOCK(map_idr_lock);
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -070051static DEFINE_IDR(link_idr);
52static DEFINE_SPINLOCK(link_idr_lock);
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080053
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070054int sysctl_unprivileged_bpf_disabled __read_mostly;
55
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 */
Martin KaFai Laudcab51f2018-05-22 15:03:31 -070076int bpf_check_uarg_tail_zero(void __user *uaddr,
77 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 unsigned char __user *addr = uaddr + expected_size;
81 int res;
Mickaël Salaün58291a72017-08-07 20:45:19 +020082
Mickaël Salaün752ba562017-08-07 20:45:20 +020083 if (unlikely(actual_size > PAGE_SIZE)) /* silly large */
84 return -E2BIG;
85
Mickaël Salaün58291a72017-08-07 20:45:19 +020086 if (actual_size <= expected_size)
87 return 0;
88
Al Virob7e4b652020-05-08 00:16:31 -040089 res = check_zeroed_user(addr, actual_size - expected_size);
90 if (res < 0)
91 return res;
92 return res ? 0 : -E2BIG;
Mickaël Salaün58291a72017-08-07 20:45:19 +020093}
94
Jakub Kicinskia3884572018-01-11 20:29:09 -080095const struct bpf_map_ops bpf_map_offload_ops = {
Martin KaFai Lauf4d05252020-08-27 18:18:06 -070096 .map_meta_equal = bpf_map_meta_equal,
Jakub Kicinskia3884572018-01-11 20:29:09 -080097 .map_alloc = bpf_map_offload_map_alloc,
98 .map_free = bpf_map_offload_map_free,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +020099 .map_check_btf = map_check_no_btf,
Jakub Kicinskia3884572018-01-11 20:29:09 -0800100};
101
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700102static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
103{
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800104 const struct bpf_map_ops *ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100105 u32 type = attr->map_type;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700106 struct bpf_map *map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800107 int err;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700108
Mark Rutland9ef09e32018-05-03 17:04:59 +0100109 if (type >= ARRAY_SIZE(bpf_map_types))
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800110 return ERR_PTR(-EINVAL);
Mark Rutland9ef09e32018-05-03 17:04:59 +0100111 type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types));
112 ops = bpf_map_types[type];
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800113 if (!ops)
Johannes Berg40077e02017-04-11 15:34:58 +0200114 return ERR_PTR(-EINVAL);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700115
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800116 if (ops->map_alloc_check) {
117 err = ops->map_alloc_check(attr);
118 if (err)
119 return ERR_PTR(err);
120 }
Jakub Kicinskia3884572018-01-11 20:29:09 -0800121 if (attr->map_ifindex)
122 ops = &bpf_map_offload_ops;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800123 map = ops->map_alloc(attr);
Johannes Berg40077e02017-04-11 15:34:58 +0200124 if (IS_ERR(map))
125 return map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800126 map->ops = ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100127 map->map_type = type;
Johannes Berg40077e02017-04-11 15:34:58 +0200128 return map;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700129}
130
Brian Vazquez15c14a32020-01-15 10:43:00 -0800131static u32 bpf_map_value_size(struct bpf_map *map)
132{
133 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
134 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
135 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
136 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
137 return round_up(map->value_size, 8) * num_possible_cpus();
138 else if (IS_FD_MAP(map))
139 return sizeof(u32);
140 else
141 return map->value_size;
142}
143
144static void maybe_wait_bpf_programs(struct bpf_map *map)
145{
146 /* Wait for any running BPF programs to complete so that
147 * userspace, when we return to it, knows that all programs
148 * that could be running use the new map value.
149 */
150 if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
151 map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
152 synchronize_rcu();
153}
154
155static int bpf_map_update_value(struct bpf_map *map, struct fd f, void *key,
156 void *value, __u64 flags)
157{
158 int err;
159
160 /* Need to create a kthread, thus must support schedule */
161 if (bpf_map_is_dev_bound(map)) {
162 return bpf_map_offload_update_elem(map, key, value, flags);
163 } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
Brian Vazquez15c14a32020-01-15 10:43:00 -0800164 map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
165 return map->ops->map_update_elem(map, key, value, flags);
Lorenz Bauer13b79d32020-08-21 11:29:45 +0100166 } else if (map->map_type == BPF_MAP_TYPE_SOCKHASH ||
167 map->map_type == BPF_MAP_TYPE_SOCKMAP) {
168 return sock_map_update_elem_sys(map, key, value, flags);
Brian Vazquez15c14a32020-01-15 10:43:00 -0800169 } else if (IS_FD_PROG_ARRAY(map)) {
170 return bpf_fd_array_map_update_elem(map, f.file, key, value,
171 flags);
172 }
173
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100174 bpf_disable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800175 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
176 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
177 err = bpf_percpu_hash_update(map, key, value, flags);
178 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
179 err = bpf_percpu_array_update(map, key, value, flags);
180 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
181 err = bpf_percpu_cgroup_storage_update(map, key, value,
182 flags);
183 } else if (IS_FD_ARRAY(map)) {
184 rcu_read_lock();
185 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
186 flags);
187 rcu_read_unlock();
188 } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
189 rcu_read_lock();
190 err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
191 flags);
192 rcu_read_unlock();
193 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
194 /* rcu_read_lock() is not needed */
195 err = bpf_fd_reuseport_array_update_elem(map, key, value,
196 flags);
197 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
198 map->map_type == BPF_MAP_TYPE_STACK) {
199 err = map->ops->map_push_elem(map, value, flags);
200 } else {
201 rcu_read_lock();
202 err = map->ops->map_update_elem(map, key, value, flags);
203 rcu_read_unlock();
204 }
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100205 bpf_enable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800206 maybe_wait_bpf_programs(map);
207
208 return err;
209}
210
211static int bpf_map_copy_value(struct bpf_map *map, void *key, void *value,
212 __u64 flags)
213{
214 void *ptr;
215 int err;
216
Brian Vazquezcb4d03a2020-01-15 10:43:01 -0800217 if (bpf_map_is_dev_bound(map))
218 return bpf_map_offload_lookup_elem(map, key, value);
Brian Vazquez15c14a32020-01-15 10:43:00 -0800219
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100220 bpf_disable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800221 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
222 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
223 err = bpf_percpu_hash_copy(map, key, value);
224 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
225 err = bpf_percpu_array_copy(map, key, value);
226 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
227 err = bpf_percpu_cgroup_storage_copy(map, key, value);
228 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
229 err = bpf_stackmap_copy(map, key, value);
230 } else if (IS_FD_ARRAY(map) || IS_FD_PROG_ARRAY(map)) {
231 err = bpf_fd_array_map_lookup_elem(map, key, value);
232 } else if (IS_FD_HASH(map)) {
233 err = bpf_fd_htab_map_lookup_elem(map, key, value);
234 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
235 err = bpf_fd_reuseport_array_lookup_elem(map, key, value);
236 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
237 map->map_type == BPF_MAP_TYPE_STACK) {
238 err = map->ops->map_peek_elem(map, value);
239 } else if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
240 /* struct_ops map requires directly updating "value" */
241 err = bpf_struct_ops_map_sys_lookup_elem(map, key, value);
242 } else {
243 rcu_read_lock();
244 if (map->ops->map_lookup_elem_sys_only)
245 ptr = map->ops->map_lookup_elem_sys_only(map, key);
246 else
247 ptr = map->ops->map_lookup_elem(map, key);
248 if (IS_ERR(ptr)) {
249 err = PTR_ERR(ptr);
250 } else if (!ptr) {
251 err = -ENOENT;
252 } else {
253 err = 0;
254 if (flags & BPF_F_LOCK)
255 /* lock 'ptr' and copy everything but lock */
256 copy_map_value_locked(map, value, ptr, true);
257 else
258 copy_map_value(map, value, ptr);
259 /* mask lock, since value wasn't zero inited */
260 check_and_init_map_lock(map, value);
261 }
262 rcu_read_unlock();
263 }
264
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +0100265 bpf_enable_instrumentation();
Brian Vazquez15c14a32020-01-15 10:43:00 -0800266 maybe_wait_bpf_programs(map);
267
268 return err;
269}
270
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100271static void *__bpf_map_area_alloc(u64 size, int numa_node, bool mmapable)
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100272{
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100273 /* We really just want to fail instead of triggering OOM killer
274 * under memory pressure, therefore we set __GFP_NORETRY to kmalloc,
275 * which is used for lower order allocation requests.
276 *
277 * It has been observed that higher order allocation requests done by
278 * vmalloc with __GFP_NORETRY being set might fail due to not trying
279 * to reclaim memory from the page cache, thus we set
280 * __GFP_RETRY_MAYFAIL to avoid such situations.
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100281 */
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100282
Christoph Hellwig041de932020-06-01 21:52:02 -0700283 const gfp_t gfp = __GFP_NOWARN | __GFP_ZERO;
284 unsigned int flags = 0;
285 unsigned long align = 1;
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100286 void *area;
287
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100288 if (size >= SIZE_MAX)
289 return NULL;
290
Andrii Nakryikofc970222019-11-17 09:28:04 -0800291 /* kmalloc()'ed memory can't be mmap()'ed */
Christoph Hellwig041de932020-06-01 21:52:02 -0700292 if (mmapable) {
293 BUG_ON(!PAGE_ALIGNED(size));
294 align = SHMLBA;
295 flags = VM_USERMAP;
296 } else if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
297 area = kmalloc_node(size, gfp | GFP_USER | __GFP_NORETRY,
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100298 numa_node);
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100299 if (area != NULL)
300 return area;
301 }
Christoph Hellwig041de932020-06-01 21:52:02 -0700302
303 return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
304 gfp | GFP_KERNEL | __GFP_RETRY_MAYFAIL, PAGE_KERNEL,
305 flags, numa_node, __builtin_return_address(0));
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100306}
307
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100308void *bpf_map_area_alloc(u64 size, int numa_node)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800309{
310 return __bpf_map_area_alloc(size, numa_node, false);
311}
312
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100313void *bpf_map_area_mmapable_alloc(u64 size, int numa_node)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800314{
315 return __bpf_map_area_alloc(size, numa_node, true);
316}
317
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100318void bpf_map_area_free(void *area)
319{
320 kvfree(area);
321}
322
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200323static u32 bpf_map_flags_retain_permanent(u32 flags)
324{
325 /* Some map creation flags are not tied to the map object but
326 * rather to the map fd instead, so they have no meaning upon
327 * map object inspection since multiple file descriptors with
328 * different (access) properties can exist here. Thus, given
329 * this has zero meaning for the map itself, lets clear these
330 * from here.
331 */
332 return flags & ~(BPF_F_RDONLY | BPF_F_WRONLY);
333}
334
Jakub Kicinskibd475642018-01-11 20:29:06 -0800335void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr)
336{
337 map->map_type = attr->map_type;
338 map->key_size = attr->key_size;
339 map->value_size = attr->value_size;
340 map->max_entries = attr->max_entries;
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200341 map->map_flags = bpf_map_flags_retain_permanent(attr->map_flags);
Jakub Kicinskibd475642018-01-11 20:29:06 -0800342 map->numa_node = bpf_map_attr_numa_node(attr);
343}
344
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700345static int bpf_charge_memlock(struct user_struct *user, u32 pages)
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700346{
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700347 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700348
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700349 if (atomic_long_add_return(pages, &user->locked_vm) > memlock_limit) {
350 atomic_long_sub(pages, &user->locked_vm);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700351 return -EPERM;
352 }
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700353 return 0;
354}
355
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700356static void bpf_uncharge_memlock(struct user_struct *user, u32 pages)
357{
Roman Gushchinb936ca62019-05-29 18:03:58 -0700358 if (user)
359 atomic_long_sub(pages, &user->locked_vm);
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700360}
361
Daniel Borkmann196e8ca2019-11-20 23:04:44 +0100362int bpf_map_charge_init(struct bpf_map_memory *mem, u64 size)
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700363{
Roman Gushchinc85d6912019-05-29 18:03:59 -0700364 u32 pages = round_up(size, PAGE_SIZE) >> PAGE_SHIFT;
365 struct user_struct *user;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700366 int ret;
367
Roman Gushchinc85d6912019-05-29 18:03:59 -0700368 if (size >= U32_MAX - PAGE_SIZE)
369 return -E2BIG;
370
371 user = get_current_user();
Roman Gushchinb936ca62019-05-29 18:03:58 -0700372 ret = bpf_charge_memlock(user, pages);
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700373 if (ret) {
374 free_uid(user);
375 return ret;
376 }
Roman Gushchinb936ca62019-05-29 18:03:58 -0700377
378 mem->pages = pages;
379 mem->user = user;
380
381 return 0;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700382}
383
Roman Gushchinb936ca62019-05-29 18:03:58 -0700384void bpf_map_charge_finish(struct bpf_map_memory *mem)
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700385{
Roman Gushchinb936ca62019-05-29 18:03:58 -0700386 bpf_uncharge_memlock(mem->user, mem->pages);
387 free_uid(mem->user);
388}
Roman Gushchin3539b962019-05-29 18:03:57 -0700389
Roman Gushchinb936ca62019-05-29 18:03:58 -0700390void bpf_map_charge_move(struct bpf_map_memory *dst,
391 struct bpf_map_memory *src)
392{
393 *dst = *src;
394
395 /* Make sure src will not be used for the redundant uncharging. */
396 memset(src, 0, sizeof(struct bpf_map_memory));
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700397}
398
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700399int bpf_map_charge_memlock(struct bpf_map *map, u32 pages)
400{
401 int ret;
402
Roman Gushchin3539b962019-05-29 18:03:57 -0700403 ret = bpf_charge_memlock(map->memory.user, pages);
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700404 if (ret)
405 return ret;
Roman Gushchin3539b962019-05-29 18:03:57 -0700406 map->memory.pages += pages;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700407 return ret;
408}
409
410void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages)
411{
Roman Gushchin3539b962019-05-29 18:03:57 -0700412 bpf_uncharge_memlock(map->memory.user, pages);
413 map->memory.pages -= pages;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700414}
415
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700416static int bpf_map_alloc_id(struct bpf_map *map)
417{
418 int id;
419
Shaohua Lib76354c2018-03-27 11:53:21 -0700420 idr_preload(GFP_KERNEL);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700421 spin_lock_bh(&map_idr_lock);
422 id = idr_alloc_cyclic(&map_idr, map, 1, INT_MAX, GFP_ATOMIC);
423 if (id > 0)
424 map->id = id;
425 spin_unlock_bh(&map_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -0700426 idr_preload_end();
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700427
428 if (WARN_ON_ONCE(!id))
429 return -ENOSPC;
430
431 return id > 0 ? 0 : id;
432}
433
Jakub Kicinskia3884572018-01-11 20:29:09 -0800434void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700435{
Eric Dumazet930651a2017-09-19 09:15:59 -0700436 unsigned long flags;
437
Jakub Kicinskia3884572018-01-11 20:29:09 -0800438 /* Offloaded maps are removed from the IDR store when their device
439 * disappears - even if someone holds an fd to them they are unusable,
440 * the memory is gone, all ops will fail; they are simply waiting for
441 * refcnt to drop to be freed.
442 */
443 if (!map->id)
444 return;
445
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700446 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700447 spin_lock_irqsave(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700448 else
449 __acquire(&map_idr_lock);
450
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700451 idr_remove(&map_idr, map->id);
Jakub Kicinskia3884572018-01-11 20:29:09 -0800452 map->id = 0;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700453
454 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700455 spin_unlock_irqrestore(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700456 else
457 __release(&map_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700458}
459
Roman Gushchin48edc1f2020-12-01 13:58:32 -0800460#ifdef CONFIG_MEMCG_KMEM
461static void bpf_map_save_memcg(struct bpf_map *map)
462{
463 map->memcg = get_mem_cgroup_from_mm(current->mm);
464}
465
466static void bpf_map_release_memcg(struct bpf_map *map)
467{
468 mem_cgroup_put(map->memcg);
469}
470
471void *bpf_map_kmalloc_node(const struct bpf_map *map, size_t size, gfp_t flags,
472 int node)
473{
474 struct mem_cgroup *old_memcg;
475 void *ptr;
476
477 old_memcg = set_active_memcg(map->memcg);
478 ptr = kmalloc_node(size, flags | __GFP_ACCOUNT, node);
479 set_active_memcg(old_memcg);
480
481 return ptr;
482}
483
484void *bpf_map_kzalloc(const struct bpf_map *map, size_t size, gfp_t flags)
485{
486 struct mem_cgroup *old_memcg;
487 void *ptr;
488
489 old_memcg = set_active_memcg(map->memcg);
490 ptr = kzalloc(size, flags | __GFP_ACCOUNT);
491 set_active_memcg(old_memcg);
492
493 return ptr;
494}
495
496void __percpu *bpf_map_alloc_percpu(const struct bpf_map *map, size_t size,
497 size_t align, gfp_t flags)
498{
499 struct mem_cgroup *old_memcg;
500 void __percpu *ptr;
501
502 old_memcg = set_active_memcg(map->memcg);
503 ptr = __alloc_percpu_gfp(size, align, flags | __GFP_ACCOUNT);
504 set_active_memcg(old_memcg);
505
506 return ptr;
507}
508
509#else
510static void bpf_map_save_memcg(struct bpf_map *map)
511{
512}
513
514static void bpf_map_release_memcg(struct bpf_map *map)
515{
516}
517#endif
518
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700519/* called from workqueue */
520static void bpf_map_free_deferred(struct work_struct *work)
521{
522 struct bpf_map *map = container_of(work, struct bpf_map, work);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700523 struct bpf_map_memory mem;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700524
Roman Gushchinb936ca62019-05-29 18:03:58 -0700525 bpf_map_charge_move(&mem, &map->memory);
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700526 security_bpf_map_free(map);
Roman Gushchin48edc1f2020-12-01 13:58:32 -0800527 bpf_map_release_memcg(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700528 /* implementation dependent freeing */
529 map->ops->map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700530 bpf_map_charge_finish(&mem);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700531}
532
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100533static void bpf_map_put_uref(struct bpf_map *map)
534{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800535 if (atomic64_dec_and_test(&map->usercnt)) {
John Fastabendba6b8de2018-04-23 15:39:23 -0700536 if (map->ops->map_release_uref)
537 map->ops->map_release_uref(map);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100538 }
539}
540
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700541/* decrement map refcnt and schedule it for freeing via workqueue
542 * (unrelying map implementation ops->map_free() might sleep)
543 */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700544static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700545{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800546 if (atomic64_dec_and_test(&map->refcnt)) {
Martin KaFai Lau34ad5582017-06-05 12:15:48 -0700547 /* bpf_map_free_id() must be called first */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700548 bpf_map_free_id(map, do_idr_lock);
Martin KaFai Lau78958fc2018-05-04 14:49:51 -0700549 btf_put(map->btf);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700550 INIT_WORK(&map->work, bpf_map_free_deferred);
551 schedule_work(&map->work);
552 }
553}
554
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700555void bpf_map_put(struct bpf_map *map)
556{
557 __bpf_map_put(map, true);
558}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700559EXPORT_SYMBOL_GPL(bpf_map_put);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700560
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100561void bpf_map_put_with_uref(struct bpf_map *map)
562{
563 bpf_map_put_uref(map);
564 bpf_map_put(map);
565}
566
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700567static int bpf_map_release(struct inode *inode, struct file *filp)
568{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200569 struct bpf_map *map = filp->private_data;
570
571 if (map->ops->map_release)
572 map->ops->map_release(map, filp);
573
574 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700575 return 0;
576}
577
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200578static fmode_t map_get_sys_perms(struct bpf_map *map, struct fd f)
579{
580 fmode_t mode = f.file->f_mode;
581
582 /* Our file permissions may have been overridden by global
583 * map permissions facing syscall side.
584 */
585 if (READ_ONCE(map->frozen))
586 mode &= ~FMODE_CAN_WRITE;
587 return mode;
588}
589
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100590#ifdef CONFIG_PROC_FS
591static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
592{
593 const struct bpf_map *map = filp->private_data;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100594 const struct bpf_array *array;
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100595 u32 type = 0, jited = 0;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100596
597 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
598 array = container_of(map, struct bpf_array, map);
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100599 type = array->aux->type;
600 jited = array->aux->jited;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100601 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100602
603 seq_printf(m,
604 "map_type:\t%u\n"
605 "key_size:\t%u\n"
606 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100607 "max_entries:\t%u\n"
Daniel Borkmann21116b72016-11-26 01:28:07 +0100608 "map_flags:\t%#x\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +0200609 "memlock:\t%llu\n"
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200610 "map_id:\t%u\n"
611 "frozen:\t%u\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100612 map->map_type,
613 map->key_size,
614 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100615 map->max_entries,
Daniel Borkmann21116b72016-11-26 01:28:07 +0100616 map->map_flags,
Roman Gushchin3539b962019-05-29 18:03:57 -0700617 map->memory.pages * 1ULL << PAGE_SHIFT,
Daniel Borkmann87df15d2019-04-09 23:20:06 +0200618 map->id,
619 READ_ONCE(map->frozen));
Daniel Borkmann2beee5f2019-11-22 21:07:56 +0100620 if (type) {
621 seq_printf(m, "owner_prog_type:\t%u\n", type);
622 seq_printf(m, "owner_jited:\t%u\n", jited);
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200623 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100624}
625#endif
626
Chenbo Feng6e71b042017-10-18 13:00:22 -0700627static ssize_t bpf_dummy_read(struct file *filp, char __user *buf, size_t siz,
628 loff_t *ppos)
629{
630 /* We need this handler such that alloc_file() enables
631 * f_mode with FMODE_CAN_READ.
632 */
633 return -EINVAL;
634}
635
636static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
637 size_t siz, loff_t *ppos)
638{
639 /* We need this handler such that alloc_file() enables
640 * f_mode with FMODE_CAN_WRITE.
641 */
642 return -EINVAL;
643}
644
Andrii Nakryikofc970222019-11-17 09:28:04 -0800645/* called for any extra memory-mapped regions (except initial) */
646static void bpf_map_mmap_open(struct vm_area_struct *vma)
647{
648 struct bpf_map *map = vma->vm_file->private_data;
649
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700650 if (vma->vm_flags & VM_MAYWRITE) {
Andrii Nakryikofc970222019-11-17 09:28:04 -0800651 mutex_lock(&map->freeze_mutex);
652 map->writecnt++;
653 mutex_unlock(&map->freeze_mutex);
654 }
655}
656
657/* called for all unmapped memory region (including initial) */
658static void bpf_map_mmap_close(struct vm_area_struct *vma)
659{
660 struct bpf_map *map = vma->vm_file->private_data;
661
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700662 if (vma->vm_flags & VM_MAYWRITE) {
Andrii Nakryikofc970222019-11-17 09:28:04 -0800663 mutex_lock(&map->freeze_mutex);
664 map->writecnt--;
665 mutex_unlock(&map->freeze_mutex);
666 }
Andrii Nakryikofc970222019-11-17 09:28:04 -0800667}
668
669static const struct vm_operations_struct bpf_map_default_vmops = {
670 .open = bpf_map_mmap_open,
671 .close = bpf_map_mmap_close,
672};
673
674static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
675{
676 struct bpf_map *map = filp->private_data;
677 int err;
678
679 if (!map->ops->map_mmap || map_value_has_spin_lock(map))
680 return -ENOTSUPP;
681
682 if (!(vma->vm_flags & VM_SHARED))
683 return -EINVAL;
684
685 mutex_lock(&map->freeze_mutex);
686
Andrii Nakryikodfeb3762020-05-18 22:38:24 -0700687 if (vma->vm_flags & VM_WRITE) {
688 if (map->frozen) {
689 err = -EPERM;
690 goto out;
691 }
692 /* map is meant to be read-only, so do not allow mapping as
693 * writable, because it's possible to leak a writable page
694 * reference and allows user-space to still modify it after
695 * freezing, while verifier will assume contents do not change
696 */
697 if (map->map_flags & BPF_F_RDONLY_PROG) {
698 err = -EACCES;
699 goto out;
700 }
Andrii Nakryikofc970222019-11-17 09:28:04 -0800701 }
702
703 /* set default open/close callbacks */
704 vma->vm_ops = &bpf_map_default_vmops;
705 vma->vm_private_data = map;
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700706 vma->vm_flags &= ~VM_MAYEXEC;
707 if (!(vma->vm_flags & VM_WRITE))
708 /* disallow re-mapping with PROT_WRITE */
709 vma->vm_flags &= ~VM_MAYWRITE;
Andrii Nakryikofc970222019-11-17 09:28:04 -0800710
711 err = map->ops->map_mmap(map, vma);
712 if (err)
713 goto out;
714
Andrii Nakryiko1f6cb192020-04-10 13:26:12 -0700715 if (vma->vm_flags & VM_MAYWRITE)
Andrii Nakryikofc970222019-11-17 09:28:04 -0800716 map->writecnt++;
717out:
718 mutex_unlock(&map->freeze_mutex);
719 return err;
720}
721
Andrii Nakryiko457f4432020-05-29 00:54:20 -0700722static __poll_t bpf_map_poll(struct file *filp, struct poll_table_struct *pts)
723{
724 struct bpf_map *map = filp->private_data;
725
726 if (map->ops->map_poll)
727 return map->ops->map_poll(map, filp, pts);
728
729 return EPOLLERR;
730}
731
Chenbo Fengf66e4482017-10-18 13:00:26 -0700732const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100733#ifdef CONFIG_PROC_FS
734 .show_fdinfo = bpf_map_show_fdinfo,
735#endif
736 .release = bpf_map_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700737 .read = bpf_dummy_read,
738 .write = bpf_dummy_write,
Andrii Nakryikofc970222019-11-17 09:28:04 -0800739 .mmap = bpf_map_mmap,
Andrii Nakryiko457f4432020-05-29 00:54:20 -0700740 .poll = bpf_map_poll,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700741};
742
Chenbo Feng6e71b042017-10-18 13:00:22 -0700743int bpf_map_new_fd(struct bpf_map *map, int flags)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100744{
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700745 int ret;
746
747 ret = security_bpf_map(map, OPEN_FMODE(flags));
748 if (ret < 0)
749 return ret;
750
Daniel Borkmannaa797812015-10-29 14:58:06 +0100751 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700752 flags | O_CLOEXEC);
753}
754
755int bpf_get_file_flag(int flags)
756{
757 if ((flags & BPF_F_RDONLY) && (flags & BPF_F_WRONLY))
758 return -EINVAL;
759 if (flags & BPF_F_RDONLY)
760 return O_RDONLY;
761 if (flags & BPF_F_WRONLY)
762 return O_WRONLY;
763 return O_RDWR;
Daniel Borkmannaa797812015-10-29 14:58:06 +0100764}
765
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700766/* helper macro to check that unused fields 'union bpf_attr' are zero */
767#define CHECK_ATTR(CMD) \
768 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
769 sizeof(attr->CMD##_LAST_FIELD), 0, \
770 sizeof(*attr) - \
771 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
772 sizeof(attr->CMD##_LAST_FIELD)) != NULL
773
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700774/* dst and src must have at least "size" number of bytes.
775 * Return strlen on success and < 0 on error.
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700776 */
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700777int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size)
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700778{
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700779 const char *end = src + size;
780 const char *orig_src = src;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700781
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700782 memset(dst, 0, size);
Daniel Borkmann3e0ddc4f2019-04-09 23:20:07 +0200783 /* Copy all isalnum(), '_' and '.' chars. */
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700784 while (src < end && *src) {
Daniel Borkmann3e0ddc4f2019-04-09 23:20:07 +0200785 if (!isalnum(*src) &&
786 *src != '_' && *src != '.')
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700787 return -EINVAL;
788 *dst++ = *src++;
789 }
790
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700791 /* No '\0' found in "size" number of bytes */
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700792 if (src == end)
793 return -EINVAL;
794
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700795 return src - orig_src;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700796}
797
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200798int map_check_no_btf(const struct bpf_map *map,
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800799 const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200800 const struct btf_type *key_type,
801 const struct btf_type *value_type)
802{
803 return -ENOTSUPP;
804}
805
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800806static int map_check_btf(struct bpf_map *map, const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200807 u32 btf_key_id, u32 btf_value_id)
808{
809 const struct btf_type *key_type, *value_type;
810 u32 key_size, value_size;
811 int ret = 0;
812
Daniel Borkmann2824ecb2019-04-09 23:20:10 +0200813 /* Some maps allow key to be unspecified. */
814 if (btf_key_id) {
815 key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
816 if (!key_type || key_size != map->key_size)
817 return -EINVAL;
818 } else {
819 key_type = btf_type_by_id(btf, 0);
820 if (!map->ops->map_check_btf)
821 return -EINVAL;
822 }
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200823
824 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
825 if (!value_type || value_size != map->value_size)
826 return -EINVAL;
827
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800828 map->spin_lock_off = btf_find_spin_lock(btf, value_type);
829
830 if (map_value_has_spin_lock(map)) {
Daniel Borkmann591fe982019-04-09 23:20:05 +0200831 if (map->map_flags & BPF_F_RDONLY_PROG)
832 return -EACCES;
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800833 if (map->map_type != BPF_MAP_TYPE_HASH &&
Alexei Starovoitove16d2f12019-01-31 15:40:05 -0800834 map->map_type != BPF_MAP_TYPE_ARRAY &&
Martin KaFai Lau6ac99e82019-04-26 16:39:39 -0700835 map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE &&
KP Singh8ea63682020-08-25 20:29:17 +0200836 map->map_type != BPF_MAP_TYPE_SK_STORAGE &&
KP Singh4cf1bc12020-11-06 10:37:40 +0000837 map->map_type != BPF_MAP_TYPE_INODE_STORAGE &&
838 map->map_type != BPF_MAP_TYPE_TASK_STORAGE)
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800839 return -ENOTSUPP;
840 if (map->spin_lock_off + sizeof(struct bpf_spin_lock) >
841 map->value_size) {
842 WARN_ONCE(1,
843 "verifier bug spin_lock_off %d value_size %d\n",
844 map->spin_lock_off, map->value_size);
845 return -EFAULT;
846 }
847 }
848
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200849 if (map->ops->map_check_btf)
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800850 ret = map->ops->map_check_btf(map, btf, key_type, value_type);
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200851
852 return ret;
853}
854
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800855#define BPF_MAP_CREATE_LAST_FIELD btf_vmlinux_value_type_id
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700856/* called via syscall */
857static int map_create(union bpf_attr *attr)
858{
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700859 int numa_node = bpf_map_attr_numa_node(attr);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700860 struct bpf_map_memory mem;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700861 struct bpf_map *map;
Chenbo Feng6e71b042017-10-18 13:00:22 -0700862 int f_flags;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700863 int err;
864
865 err = CHECK_ATTR(BPF_MAP_CREATE);
866 if (err)
867 return -EINVAL;
868
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800869 if (attr->btf_vmlinux_value_type_id) {
870 if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS ||
871 attr->btf_key_type_id || attr->btf_value_type_id)
872 return -EINVAL;
873 } else if (attr->btf_key_type_id && !attr->btf_value_type_id) {
874 return -EINVAL;
875 }
876
Chenbo Feng6e71b042017-10-18 13:00:22 -0700877 f_flags = bpf_get_file_flag(attr->map_flags);
878 if (f_flags < 0)
879 return f_flags;
880
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700881 if (numa_node != NUMA_NO_NODE &&
Eric Dumazet96e5ae42017-09-04 22:41:02 -0700882 ((unsigned int)numa_node >= nr_node_ids ||
883 !node_online(numa_node)))
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700884 return -EINVAL;
885
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700886 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
887 map = find_and_alloc_map(attr);
888 if (IS_ERR(map))
889 return PTR_ERR(map);
890
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -0700891 err = bpf_obj_name_cpy(map->name, attr->map_name,
892 sizeof(attr->map_name));
893 if (err < 0)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700894 goto free_map;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -0700895
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800896 atomic64_set(&map->refcnt, 1);
897 atomic64_set(&map->usercnt, 1);
Andrii Nakryikofc970222019-11-17 09:28:04 -0800898 mutex_init(&map->freeze_mutex);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700899
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800900 map->spin_lock_off = -EINVAL;
901 if (attr->btf_key_type_id || attr->btf_value_type_id ||
902 /* Even the map's value is a kernel's struct,
903 * the bpf_prog.o must have BTF to begin with
904 * to figure out the corresponding kernel's
905 * counter part. Thus, attr->btf_fd has
906 * to be valid also.
907 */
908 attr->btf_vmlinux_value_type_id) {
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700909 struct btf *btf;
910
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700911 btf = btf_get_by_fd(attr->btf_fd);
912 if (IS_ERR(btf)) {
913 err = PTR_ERR(btf);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700914 goto free_map;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700915 }
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800916 map->btf = btf;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700917
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800918 if (attr->btf_value_type_id) {
919 err = map_check_btf(map, btf, attr->btf_key_type_id,
920 attr->btf_value_type_id);
921 if (err)
922 goto free_map;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700923 }
924
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -0700925 map->btf_key_type_id = attr->btf_key_type_id;
926 map->btf_value_type_id = attr->btf_value_type_id;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -0800927 map->btf_vmlinux_value_type_id =
928 attr->btf_vmlinux_value_type_id;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700929 }
930
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700931 err = security_bpf_map_alloc(map);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700932 if (err)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700933 goto free_map;
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700934
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700935 err = bpf_map_alloc_id(map);
936 if (err)
Roman Gushchinb936ca62019-05-29 18:03:58 -0700937 goto free_map_sec;
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700938
Roman Gushchin48edc1f2020-12-01 13:58:32 -0800939 bpf_map_save_memcg(map);
940
Chenbo Feng6e71b042017-10-18 13:00:22 -0700941 err = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700942 if (err < 0) {
943 /* failed to allocate fd.
Peng Sun352d20d2019-02-27 22:36:25 +0800944 * bpf_map_put_with_uref() is needed because the above
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700945 * bpf_map_alloc_id() has published the map
946 * to the userspace and the userspace may
947 * have refcnt-ed it through BPF_MAP_GET_FD_BY_ID.
948 */
Peng Sun352d20d2019-02-27 22:36:25 +0800949 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700950 return err;
951 }
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700952
953 return err;
954
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700955free_map_sec:
956 security_bpf_map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700957free_map:
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700958 btf_put(map->btf);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700959 bpf_map_charge_move(&mem, &map->memory);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700960 map->ops->map_free(map);
Roman Gushchinb936ca62019-05-29 18:03:58 -0700961 bpf_map_charge_finish(&mem);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700962 return err;
963}
964
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700965/* if error is returned, fd is released.
966 * On success caller should complete fd access with matching fdput()
967 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100968struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700969{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700970 if (!f.file)
971 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700972 if (f.file->f_op != &bpf_map_fops) {
973 fdput(f);
974 return ERR_PTR(-EINVAL);
975 }
976
Daniel Borkmannc2101292015-10-29 14:58:07 +0100977 return f.file->private_data;
978}
979
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800980void bpf_map_inc(struct bpf_map *map)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100981{
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800982 atomic64_inc(&map->refcnt);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100983}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700984EXPORT_SYMBOL_GPL(bpf_map_inc);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100985
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -0800986void bpf_map_inc_with_uref(struct bpf_map *map)
987{
988 atomic64_inc(&map->refcnt);
989 atomic64_inc(&map->usercnt);
990}
991EXPORT_SYMBOL_GPL(bpf_map_inc_with_uref);
992
Martin KaFai Lau1ed4d922020-02-25 15:04:21 -0800993struct bpf_map *bpf_map_get(u32 ufd)
994{
995 struct fd f = fdget(ufd);
996 struct bpf_map *map;
997
998 map = __bpf_map_get(f);
999 if (IS_ERR(map))
1000 return map;
1001
1002 bpf_map_inc(map);
1003 fdput(f);
1004
1005 return map;
1006}
1007
Daniel Borkmannc9da1612015-11-24 21:28:15 +01001008struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +01001009{
1010 struct fd f = fdget(ufd);
1011 struct bpf_map *map;
1012
1013 map = __bpf_map_get(f);
1014 if (IS_ERR(map))
1015 return map;
1016
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001017 bpf_map_inc_with_uref(map);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001018 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001019
1020 return map;
1021}
1022
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001023/* map_idr_lock should have been held */
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001024static struct bpf_map *__bpf_map_inc_not_zero(struct bpf_map *map, bool uref)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001025{
1026 int refold;
1027
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001028 refold = atomic64_fetch_add_unless(&map->refcnt, 1, 0);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001029 if (!refold)
1030 return ERR_PTR(-ENOENT);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001031 if (uref)
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001032 atomic64_inc(&map->usercnt);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07001033
1034 return map;
1035}
1036
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001037struct bpf_map *bpf_map_inc_not_zero(struct bpf_map *map)
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07001038{
1039 spin_lock_bh(&map_idr_lock);
Andrii Nakryiko1e0bd5a2019-11-17 09:28:02 -08001040 map = __bpf_map_inc_not_zero(map, false);
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07001041 spin_unlock_bh(&map_idr_lock);
1042
1043 return map;
1044}
1045EXPORT_SYMBOL_GPL(bpf_map_inc_not_zero);
1046
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -08001047int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
1048{
1049 return -ENOTSUPP;
1050}
1051
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001052static void *__bpf_copy_key(void __user *ukey, u64 key_size)
1053{
1054 if (key_size)
1055 return memdup_user(ukey, key_size);
1056
1057 if (ukey)
1058 return ERR_PTR(-EINVAL);
1059
1060 return NULL;
1061}
1062
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001063/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001064#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001065
1066static int map_lookup_elem(union bpf_attr *attr)
1067{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001068 void __user *ukey = u64_to_user_ptr(attr->key);
1069 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001070 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001071 struct bpf_map *map;
Brian Vazquez15c14a32020-01-15 10:43:00 -08001072 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001073 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001074 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001075 int err;
1076
1077 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
1078 return -EINVAL;
1079
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001080 if (attr->flags & ~BPF_F_LOCK)
1081 return -EINVAL;
1082
Daniel Borkmann592867b2015-09-08 18:00:09 +02001083 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001084 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001085 if (IS_ERR(map))
1086 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001087 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001088 err = -EPERM;
1089 goto err_put;
1090 }
1091
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001092 if ((attr->flags & BPF_F_LOCK) &&
1093 !map_value_has_spin_lock(map)) {
1094 err = -EINVAL;
1095 goto err_put;
1096 }
1097
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001098 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001099 if (IS_ERR(key)) {
1100 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001101 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001102 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001103
Brian Vazquez15c14a32020-01-15 10:43:00 -08001104 value_size = bpf_map_value_size(map);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001105
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001106 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001107 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001108 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001109 goto free_key;
1110
Brian Vazquez15c14a32020-01-15 10:43:00 -08001111 err = bpf_map_copy_value(map, key, value, attr->flags);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001112 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001113 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001114
1115 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001116 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001117 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001118
1119 err = 0;
1120
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -08001121free_value:
1122 kfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001123free_key:
1124 kfree(key);
1125err_put:
1126 fdput(f);
1127 return err;
1128}
1129
Daniel Colascione1ae80cf2018-10-12 03:54:27 -07001130
Alexei Starovoitov3274f522014-11-13 17:36:44 -08001131#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001132
1133static int map_update_elem(union bpf_attr *attr)
1134{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001135 void __user *ukey = u64_to_user_ptr(attr->key);
1136 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001137 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001138 struct bpf_map *map;
1139 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001140 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001141 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001142 int err;
1143
1144 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
1145 return -EINVAL;
1146
Daniel Borkmann592867b2015-09-08 18:00:09 +02001147 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001148 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001149 if (IS_ERR(map))
1150 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001151 if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001152 err = -EPERM;
1153 goto err_put;
1154 }
1155
Alexei Starovoitov96049f32019-01-31 15:40:09 -08001156 if ((attr->flags & BPF_F_LOCK) &&
1157 !map_value_has_spin_lock(map)) {
1158 err = -EINVAL;
1159 goto err_put;
1160 }
1161
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001162 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001163 if (IS_ERR(key)) {
1164 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001165 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001166 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001167
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001168 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -08001169 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Roman Gushchinb741f162018-09-28 14:45:43 +00001170 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
1171 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001172 value_size = round_up(map->value_size, 8) * num_possible_cpus();
1173 else
1174 value_size = map->value_size;
1175
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001176 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001177 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001178 if (!value)
1179 goto free_key;
1180
1181 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -08001182 if (copy_from_user(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001183 goto free_value;
1184
Brian Vazquez15c14a32020-01-15 10:43:00 -08001185 err = bpf_map_update_value(map, f, key, value, attr->flags);
Jesper Dangaard Brouer6710e112017-10-16 12:19:28 +02001186
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001187free_value:
1188 kfree(value);
1189free_key:
1190 kfree(key);
1191err_put:
1192 fdput(f);
1193 return err;
1194}
1195
1196#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
1197
1198static int map_delete_elem(union bpf_attr *attr)
1199{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001200 void __user *ukey = u64_to_user_ptr(attr->key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001201 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001202 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001203 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001204 void *key;
1205 int err;
1206
1207 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
1208 return -EINVAL;
1209
Daniel Borkmann592867b2015-09-08 18:00:09 +02001210 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001211 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001212 if (IS_ERR(map))
1213 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001214 if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001215 err = -EPERM;
1216 goto err_put;
1217 }
1218
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001219 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001220 if (IS_ERR(key)) {
1221 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001222 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001223 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001224
Jakub Kicinskia3884572018-01-11 20:29:09 -08001225 if (bpf_map_is_dev_bound(map)) {
1226 err = bpf_map_offload_delete_elem(map, key);
1227 goto out;
Martin KaFai Lau85d33df2020-01-08 16:35:05 -08001228 } else if (IS_FD_PROG_ARRAY(map) ||
1229 map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
1230 /* These maps require sleepable context */
Daniel Borkmannda765a22019-11-22 21:07:58 +01001231 err = map->ops->map_delete_elem(map, key);
1232 goto out;
Jakub Kicinskia3884572018-01-11 20:29:09 -08001233 }
1234
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001235 bpf_disable_instrumentation();
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001236 rcu_read_lock();
1237 err = map->ops->map_delete_elem(map, key);
1238 rcu_read_unlock();
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001239 bpf_enable_instrumentation();
Daniel Colascione1ae80cf2018-10-12 03:54:27 -07001240 maybe_wait_bpf_programs(map);
Jakub Kicinskia3884572018-01-11 20:29:09 -08001241out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001242 kfree(key);
1243err_put:
1244 fdput(f);
1245 return err;
1246}
1247
1248/* last field in 'union bpf_attr' used by this command */
1249#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
1250
1251static int map_get_next_key(union bpf_attr *attr)
1252{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001253 void __user *ukey = u64_to_user_ptr(attr->key);
1254 void __user *unext_key = u64_to_user_ptr(attr->next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001255 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001256 struct bpf_map *map;
1257 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001258 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001259 int err;
1260
1261 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
1262 return -EINVAL;
1263
Daniel Borkmann592867b2015-09-08 18:00:09 +02001264 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001265 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001266 if (IS_ERR(map))
1267 return PTR_ERR(map);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001268 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
Chenbo Feng6e71b042017-10-18 13:00:22 -07001269 err = -EPERM;
1270 goto err_put;
1271 }
1272
Teng Qin8fe45922017-04-24 19:00:37 -07001273 if (ukey) {
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001274 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001275 if (IS_ERR(key)) {
1276 err = PTR_ERR(key);
Teng Qin8fe45922017-04-24 19:00:37 -07001277 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001278 }
Teng Qin8fe45922017-04-24 19:00:37 -07001279 } else {
1280 key = NULL;
1281 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001282
1283 err = -ENOMEM;
1284 next_key = kmalloc(map->key_size, GFP_USER);
1285 if (!next_key)
1286 goto free_key;
1287
Jakub Kicinskia3884572018-01-11 20:29:09 -08001288 if (bpf_map_is_dev_bound(map)) {
1289 err = bpf_map_offload_get_next_key(map, key, next_key);
1290 goto out;
1291 }
1292
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001293 rcu_read_lock();
1294 err = map->ops->map_get_next_key(map, key, next_key);
1295 rcu_read_unlock();
Jakub Kicinskia3884572018-01-11 20:29:09 -08001296out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001297 if (err)
1298 goto free_next_key;
1299
1300 err = -EFAULT;
1301 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
1302 goto free_next_key;
1303
1304 err = 0;
1305
1306free_next_key:
1307 kfree(next_key);
1308free_key:
1309 kfree(key);
1310err_put:
1311 fdput(f);
1312 return err;
1313}
1314
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001315int generic_map_delete_batch(struct bpf_map *map,
1316 const union bpf_attr *attr,
1317 union bpf_attr __user *uattr)
1318{
1319 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1320 u32 cp, max_count;
1321 int err = 0;
1322 void *key;
1323
1324 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1325 return -EINVAL;
1326
1327 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1328 !map_value_has_spin_lock(map)) {
1329 return -EINVAL;
1330 }
1331
1332 max_count = attr->batch.count;
1333 if (!max_count)
1334 return 0;
1335
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001336 key = kmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
1337 if (!key)
1338 return -ENOMEM;
1339
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001340 for (cp = 0; cp < max_count; cp++) {
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001341 err = -EFAULT;
1342 if (copy_from_user(key, keys + cp * map->key_size,
1343 map->key_size))
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001344 break;
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001345
1346 if (bpf_map_is_dev_bound(map)) {
1347 err = bpf_map_offload_delete_elem(map, key);
1348 break;
1349 }
1350
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001351 bpf_disable_instrumentation();
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001352 rcu_read_lock();
1353 err = map->ops->map_delete_elem(map, key);
1354 rcu_read_unlock();
Thomas Gleixnerb6e5dae2020-02-24 15:01:49 +01001355 bpf_enable_instrumentation();
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001356 maybe_wait_bpf_programs(map);
1357 if (err)
1358 break;
1359 }
1360 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
1361 err = -EFAULT;
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001362
1363 kfree(key);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001364 return err;
1365}
1366
1367int generic_map_update_batch(struct bpf_map *map,
1368 const union bpf_attr *attr,
1369 union bpf_attr __user *uattr)
1370{
1371 void __user *values = u64_to_user_ptr(attr->batch.values);
1372 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1373 u32 value_size, cp, max_count;
1374 int ufd = attr->map_fd;
1375 void *key, *value;
1376 struct fd f;
1377 int err = 0;
1378
1379 f = fdget(ufd);
1380 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1381 return -EINVAL;
1382
1383 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1384 !map_value_has_spin_lock(map)) {
1385 return -EINVAL;
1386 }
1387
1388 value_size = bpf_map_value_size(map);
1389
1390 max_count = attr->batch.count;
1391 if (!max_count)
1392 return 0;
1393
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001394 key = kmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
1395 if (!key)
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001396 return -ENOMEM;
1397
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001398 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
1399 if (!value) {
1400 kfree(key);
1401 return -ENOMEM;
1402 }
1403
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001404 for (cp = 0; cp < max_count; cp++) {
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001405 err = -EFAULT;
Brian Vazquez2e3a94a2020-01-19 11:40:40 -08001406 if (copy_from_user(key, keys + cp * map->key_size,
1407 map->key_size) ||
1408 copy_from_user(value, values + cp * value_size, value_size))
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08001409 break;
1410
1411 err = bpf_map_update_value(map, f, key, value,
1412 attr->batch.elem_flags);
1413
1414 if (err)
1415 break;
1416 }
1417
1418 if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp)))
1419 err = -EFAULT;
1420
1421 kfree(value);
1422 kfree(key);
1423 return err;
1424}
1425
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001426#define MAP_LOOKUP_RETRIES 3
1427
1428int generic_map_lookup_batch(struct bpf_map *map,
1429 const union bpf_attr *attr,
1430 union bpf_attr __user *uattr)
1431{
1432 void __user *uobatch = u64_to_user_ptr(attr->batch.out_batch);
1433 void __user *ubatch = u64_to_user_ptr(attr->batch.in_batch);
1434 void __user *values = u64_to_user_ptr(attr->batch.values);
1435 void __user *keys = u64_to_user_ptr(attr->batch.keys);
1436 void *buf, *buf_prevkey, *prev_key, *key, *value;
1437 int err, retry = MAP_LOOKUP_RETRIES;
1438 u32 value_size, cp, max_count;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001439
1440 if (attr->batch.elem_flags & ~BPF_F_LOCK)
1441 return -EINVAL;
1442
1443 if ((attr->batch.elem_flags & BPF_F_LOCK) &&
1444 !map_value_has_spin_lock(map))
1445 return -EINVAL;
1446
1447 value_size = bpf_map_value_size(map);
1448
1449 max_count = attr->batch.count;
1450 if (!max_count)
1451 return 0;
1452
1453 if (put_user(0, &uattr->batch.count))
1454 return -EFAULT;
1455
1456 buf_prevkey = kmalloc(map->key_size, GFP_USER | __GFP_NOWARN);
1457 if (!buf_prevkey)
1458 return -ENOMEM;
1459
1460 buf = kmalloc(map->key_size + value_size, GFP_USER | __GFP_NOWARN);
1461 if (!buf) {
Denis Efremovbb2359f2020-06-01 19:28:14 +03001462 kfree(buf_prevkey);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001463 return -ENOMEM;
1464 }
1465
1466 err = -EFAULT;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08001467 prev_key = NULL;
1468 if (ubatch && copy_from_user(buf_prevkey, ubatch, map->key_size))
1469 goto free_buf;
1470 key = buf;
1471 value = key + map->key_size;
1472 if (ubatch)
1473 prev_key = buf_prevkey;
1474
1475 for (cp = 0; cp < max_count;) {
1476 rcu_read_lock();
1477 err = map->ops->map_get_next_key(map, prev_key, key);
1478 rcu_read_unlock();
1479 if (err)
1480 break;
1481 err = bpf_map_copy_value(map, key, value,
1482 attr->batch.elem_flags);
1483
1484 if (err == -ENOENT) {
1485 if (retry) {
1486 retry--;
1487 continue;
1488 }
1489 err = -EINTR;
1490 break;
1491 }
1492
1493 if (err)
1494 goto free_buf;
1495
1496 if (copy_to_user(keys + cp * map->key_size, key,
1497 map->key_size)) {
1498 err = -EFAULT;
1499 goto free_buf;
1500 }
1501 if (copy_to_user(values + cp * value_size, value, value_size)) {
1502 err = -EFAULT;
1503 goto free_buf;
1504 }
1505
1506 if (!prev_key)
1507 prev_key = buf_prevkey;
1508
1509 swap(prev_key, key);
1510 retry = MAP_LOOKUP_RETRIES;
1511 cp++;
1512 }
1513
1514 if (err == -EFAULT)
1515 goto free_buf;
1516
1517 if ((copy_to_user(&uattr->batch.count, &cp, sizeof(cp)) ||
1518 (cp && copy_to_user(uobatch, prev_key, map->key_size))))
1519 err = -EFAULT;
1520
1521free_buf:
1522 kfree(buf_prevkey);
1523 kfree(buf);
1524 return err;
1525}
1526
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001527#define BPF_MAP_LOOKUP_AND_DELETE_ELEM_LAST_FIELD value
1528
1529static int map_lookup_and_delete_elem(union bpf_attr *attr)
1530{
1531 void __user *ukey = u64_to_user_ptr(attr->key);
1532 void __user *uvalue = u64_to_user_ptr(attr->value);
1533 int ufd = attr->map_fd;
1534 struct bpf_map *map;
Alexei Starovoitov540fefc2018-10-19 13:52:38 -07001535 void *key, *value;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001536 u32 value_size;
1537 struct fd f;
1538 int err;
1539
1540 if (CHECK_ATTR(BPF_MAP_LOOKUP_AND_DELETE_ELEM))
1541 return -EINVAL;
1542
1543 f = fdget(ufd);
1544 map = __bpf_map_get(f);
1545 if (IS_ERR(map))
1546 return PTR_ERR(map);
Anton Protopopov1ea0f912020-05-27 18:56:59 +00001547 if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) ||
1548 !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001549 err = -EPERM;
1550 goto err_put;
1551 }
1552
1553 key = __bpf_copy_key(ukey, map->key_size);
1554 if (IS_ERR(key)) {
1555 err = PTR_ERR(key);
1556 goto err_put;
1557 }
1558
1559 value_size = map->value_size;
1560
1561 err = -ENOMEM;
1562 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
1563 if (!value)
1564 goto free_key;
1565
1566 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);
1569 } else {
1570 err = -ENOTSUPP;
1571 }
1572
1573 if (err)
1574 goto free_value;
1575
Wei Yongjun7f645462020-04-30 08:18:51 +00001576 if (copy_to_user(uvalue, value, value_size) != 0) {
1577 err = -EFAULT;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001578 goto free_value;
Wei Yongjun7f645462020-04-30 08:18:51 +00001579 }
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001580
1581 err = 0;
1582
1583free_value:
1584 kfree(value);
1585free_key:
1586 kfree(key);
1587err_put:
1588 fdput(f);
1589 return err;
1590}
1591
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001592#define BPF_MAP_FREEZE_LAST_FIELD map_fd
1593
1594static int map_freeze(const union bpf_attr *attr)
1595{
1596 int err = 0, ufd = attr->map_fd;
1597 struct bpf_map *map;
1598 struct fd f;
1599
1600 if (CHECK_ATTR(BPF_MAP_FREEZE))
1601 return -EINVAL;
1602
1603 f = fdget(ufd);
1604 map = __bpf_map_get(f);
1605 if (IS_ERR(map))
1606 return PTR_ERR(map);
Andrii Nakryikofc970222019-11-17 09:28:04 -08001607
Martin KaFai Lau849b4d92020-03-04 17:34:54 -08001608 if (map->map_type == BPF_MAP_TYPE_STRUCT_OPS) {
1609 fdput(f);
1610 return -ENOTSUPP;
1611 }
1612
Andrii Nakryikofc970222019-11-17 09:28:04 -08001613 mutex_lock(&map->freeze_mutex);
1614
1615 if (map->writecnt) {
1616 err = -EBUSY;
1617 goto err_put;
1618 }
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001619 if (READ_ONCE(map->frozen)) {
1620 err = -EBUSY;
1621 goto err_put;
1622 }
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07001623 if (!bpf_capable()) {
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001624 err = -EPERM;
1625 goto err_put;
1626 }
1627
1628 WRITE_ONCE(map->frozen, true);
1629err_put:
Andrii Nakryikofc970222019-11-17 09:28:04 -08001630 mutex_unlock(&map->freeze_mutex);
Daniel Borkmann87df15d2019-04-09 23:20:06 +02001631 fdput(f);
1632 return err;
1633}
1634
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001635static const struct bpf_prog_ops * const bpf_prog_types[] = {
Alexei Starovoitov91cc1a92019-11-14 10:57:15 -08001636#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001637 [_id] = & _name ## _prog_ops,
1638#define BPF_MAP_TYPE(_id, _ops)
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07001639#define BPF_LINK_TYPE(_id, _name)
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001640#include <linux/bpf_types.h>
1641#undef BPF_PROG_TYPE
1642#undef BPF_MAP_TYPE
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07001643#undef BPF_LINK_TYPE
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001644};
1645
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001646static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
1647{
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001648 const struct bpf_prog_ops *ops;
1649
1650 if (type >= ARRAY_SIZE(bpf_prog_types))
1651 return -EINVAL;
1652 type = array_index_nospec(type, ARRAY_SIZE(bpf_prog_types));
1653 ops = bpf_prog_types[type];
1654 if (!ops)
Johannes Bergbe9370a2017-04-11 15:34:57 +02001655 return -EINVAL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001656
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001657 if (!bpf_prog_is_dev_bound(prog->aux))
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001658 prog->aux->ops = ops;
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001659 else
1660 prog->aux->ops = &bpf_offload_prog_ops;
Johannes Bergbe9370a2017-04-11 15:34:57 +02001661 prog->type = type;
1662 return 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001663}
1664
Daniel Borkmannbae141f2019-12-06 22:49:34 +01001665enum bpf_audit {
1666 BPF_AUDIT_LOAD,
1667 BPF_AUDIT_UNLOAD,
1668 BPF_AUDIT_MAX,
1669};
1670
1671static const char * const bpf_audit_str[BPF_AUDIT_MAX] = {
1672 [BPF_AUDIT_LOAD] = "LOAD",
1673 [BPF_AUDIT_UNLOAD] = "UNLOAD",
1674};
1675
1676static void bpf_audit_prog(const struct bpf_prog *prog, unsigned int op)
1677{
1678 struct audit_context *ctx = NULL;
1679 struct audit_buffer *ab;
1680
1681 if (WARN_ON_ONCE(op >= BPF_AUDIT_MAX))
1682 return;
1683 if (audit_enabled == AUDIT_OFF)
1684 return;
1685 if (op == BPF_AUDIT_LOAD)
1686 ctx = audit_context();
1687 ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_BPF);
1688 if (unlikely(!ab))
1689 return;
1690 audit_log_format(ab, "prog-id=%u op=%s",
1691 prog->aux->id, bpf_audit_str[op]);
1692 audit_log_end(ab);
1693}
1694
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001695int __bpf_prog_charge(struct user_struct *user, u32 pages)
1696{
1697 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
1698 unsigned long user_bufs;
1699
1700 if (user) {
1701 user_bufs = atomic_long_add_return(pages, &user->locked_vm);
1702 if (user_bufs > memlock_limit) {
1703 atomic_long_sub(pages, &user->locked_vm);
1704 return -EPERM;
1705 }
1706 }
1707
1708 return 0;
1709}
1710
1711void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
1712{
1713 if (user)
1714 atomic_long_sub(pages, &user->locked_vm);
1715}
1716
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001717static int bpf_prog_charge_memlock(struct bpf_prog *prog)
1718{
1719 struct user_struct *user = get_current_user();
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001720 int ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001721
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001722 ret = __bpf_prog_charge(user, prog->pages);
1723 if (ret) {
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001724 free_uid(user);
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001725 return ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001726 }
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001727
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001728 prog->aux->user = user;
1729 return 0;
1730}
1731
1732static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
1733{
1734 struct user_struct *user = prog->aux->user;
1735
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001736 __bpf_prog_uncharge(user, prog->pages);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001737 free_uid(user);
1738}
1739
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001740static int bpf_prog_alloc_id(struct bpf_prog *prog)
1741{
1742 int id;
1743
Shaohua Lib76354c2018-03-27 11:53:21 -07001744 idr_preload(GFP_KERNEL);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001745 spin_lock_bh(&prog_idr_lock);
1746 id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
1747 if (id > 0)
1748 prog->aux->id = id;
1749 spin_unlock_bh(&prog_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -07001750 idr_preload_end();
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001751
1752 /* id is in [1, INT_MAX) */
1753 if (WARN_ON_ONCE(!id))
1754 return -ENOSPC;
1755
1756 return id > 0 ? 0 : id;
1757}
1758
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001759void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001760{
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001761 /* cBPF to eBPF migrations are currently not in the idr store.
1762 * Offloaded programs are removed from the store when their device
1763 * disappears - even if someone grabs an fd to them they are unusable,
1764 * simply waiting for refcnt to drop to be freed.
1765 */
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001766 if (!prog->aux->id)
1767 return;
1768
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001769 if (do_idr_lock)
1770 spin_lock_bh(&prog_idr_lock);
1771 else
1772 __acquire(&prog_idr_lock);
1773
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001774 idr_remove(&prog_idr, prog->aux->id);
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001775 prog->aux->id = 0;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001776
1777 if (do_idr_lock)
1778 spin_unlock_bh(&prog_idr_lock);
1779 else
1780 __release(&prog_idr_lock);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001781}
1782
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001783static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001784{
1785 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
1786
Daniel Borkmann3b4d9eb2019-10-22 23:30:38 +02001787 kvfree(aux->func_info);
Alexei Starovoitov8c1b6e62019-11-14 10:57:16 -08001788 kfree(aux->func_info_aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001789 bpf_prog_uncharge_memlock(aux->prog);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001790 security_bpf_prog_free(aux);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001791 bpf_prog_free(aux->prog);
1792}
1793
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001794static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred)
1795{
1796 bpf_prog_kallsyms_del_all(prog);
1797 btf_put(prog->aux->btf);
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001798 bpf_prog_free_linfo(prog);
1799
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07001800 if (deferred) {
1801 if (prog->aux->sleepable)
1802 call_rcu_tasks_trace(&prog->aux->rcu, __bpf_prog_put_rcu);
1803 else
1804 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1805 } else {
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001806 __bpf_prog_put_rcu(&prog->aux->rcu);
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07001807 }
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001808}
1809
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001810static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001811{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001812 if (atomic64_dec_and_test(&prog->aux->refcnt)) {
Song Liu6ee52e22019-01-17 08:15:15 -08001813 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
Daniel Borkmannbae141f2019-12-06 22:49:34 +01001814 bpf_audit_prog(prog, BPF_AUDIT_UNLOAD);
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001815 /* bpf_prog_free_id() must be called first */
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001816 bpf_prog_free_id(prog, do_idr_lock);
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02001817 __bpf_prog_put_noref(prog, true);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01001818 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001819}
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001820
1821void bpf_prog_put(struct bpf_prog *prog)
1822{
1823 __bpf_prog_put(prog, true);
1824}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +01001825EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001826
1827static int bpf_prog_release(struct inode *inode, struct file *filp)
1828{
1829 struct bpf_prog *prog = filp->private_data;
1830
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001831 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001832 return 0;
1833}
1834
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001835static void bpf_prog_get_stats(const struct bpf_prog *prog,
1836 struct bpf_prog_stats *stats)
1837{
1838 u64 nsecs = 0, cnt = 0;
1839 int cpu;
1840
1841 for_each_possible_cpu(cpu) {
1842 const struct bpf_prog_stats *st;
1843 unsigned int start;
1844 u64 tnsecs, tcnt;
1845
1846 st = per_cpu_ptr(prog->aux->stats, cpu);
1847 do {
1848 start = u64_stats_fetch_begin_irq(&st->syncp);
1849 tnsecs = st->nsecs;
1850 tcnt = st->cnt;
1851 } while (u64_stats_fetch_retry_irq(&st->syncp, start));
1852 nsecs += tnsecs;
1853 cnt += tcnt;
1854 }
1855 stats->nsecs = nsecs;
1856 stats->cnt = cnt;
1857}
1858
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001859#ifdef CONFIG_PROC_FS
1860static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
1861{
1862 const struct bpf_prog *prog = filp->private_data;
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001863 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001864 struct bpf_prog_stats stats;
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001865
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001866 bpf_prog_get_stats(prog, &stats);
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001867 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001868 seq_printf(m,
1869 "prog_type:\t%u\n"
1870 "prog_jited:\t%u\n"
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001871 "prog_tag:\t%s\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +02001872 "memlock:\t%llu\n"
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001873 "prog_id:\t%u\n"
1874 "run_time_ns:\t%llu\n"
1875 "run_cnt:\t%llu\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,
1882 stats.cnt);
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001883}
1884#endif
1885
Chenbo Fengf66e4482017-10-18 13:00:26 -07001886const struct file_operations bpf_prog_fops = {
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001887#ifdef CONFIG_PROC_FS
1888 .show_fdinfo = bpf_prog_show_fdinfo,
1889#endif
1890 .release = bpf_prog_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -07001891 .read = bpf_dummy_read,
1892 .write = bpf_dummy_write,
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001893};
1894
Daniel Borkmannb2197752015-10-29 14:58:09 +01001895int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +01001896{
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001897 int ret;
1898
1899 ret = security_bpf_prog(prog);
1900 if (ret < 0)
1901 return ret;
1902
Daniel Borkmannaa797812015-10-29 14:58:06 +01001903 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
1904 O_RDWR | O_CLOEXEC);
1905}
1906
Daniel Borkmann113214b2016-06-30 17:24:44 +02001907static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001908{
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001909 if (!f.file)
1910 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001911 if (f.file->f_op != &bpf_prog_fops) {
1912 fdput(f);
1913 return ERR_PTR(-EINVAL);
1914 }
1915
Daniel Borkmannc2101292015-10-29 14:58:07 +01001916 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001917}
1918
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001919void bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001920{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001921 atomic64_add(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001922}
Brenden Blanco59d36562016-07-19 12:16:46 -07001923EXPORT_SYMBOL_GPL(bpf_prog_add);
1924
Daniel Borkmannc5405942016-11-09 22:02:34 +01001925void bpf_prog_sub(struct bpf_prog *prog, int i)
1926{
1927 /* Only to be used for undoing previous bpf_prog_add() in some
1928 * error path. We still know that another entity in our call
1929 * path holds a reference to the program, thus atomic_sub() can
1930 * be safely used in such cases!
1931 */
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001932 WARN_ON(atomic64_sub_return(i, &prog->aux->refcnt) == 0);
Daniel Borkmannc5405942016-11-09 22:02:34 +01001933}
1934EXPORT_SYMBOL_GPL(bpf_prog_sub);
1935
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001936void bpf_prog_inc(struct bpf_prog *prog)
Brenden Blanco59d36562016-07-19 12:16:46 -07001937{
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001938 atomic64_inc(&prog->aux->refcnt);
Brenden Blanco59d36562016-07-19 12:16:46 -07001939}
Daniel Borkmann97bc4022016-11-19 01:45:00 +01001940EXPORT_SYMBOL_GPL(bpf_prog_inc);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001941
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001942/* prog_idr_lock should have been held */
John Fastabenda6f6df62017-08-15 22:32:22 -07001943struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001944{
1945 int refold;
1946
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001947 refold = atomic64_fetch_add_unless(&prog->aux->refcnt, 1, 0);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001948
1949 if (!refold)
1950 return ERR_PTR(-ENOENT);
1951
1952 return prog;
1953}
John Fastabenda6f6df62017-08-15 22:32:22 -07001954EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001955
Al Viro040ee692017-12-02 20:20:38 -05001956bool bpf_prog_get_ok(struct bpf_prog *prog,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001957 enum bpf_prog_type *attach_type, bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001958{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001959 /* not an attachment, just a refcount inc, always allow */
1960 if (!attach_type)
1961 return true;
Jakub Kicinski248f3462017-11-03 13:56:20 -07001962
1963 if (prog->type != *attach_type)
1964 return false;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001965 if (bpf_prog_is_dev_bound(prog->aux) && !attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001966 return false;
1967
1968 return true;
1969}
1970
1971static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001972 bool attach_drv)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001973{
1974 struct fd f = fdget(ufd);
1975 struct bpf_prog *prog;
1976
Daniel Borkmann113214b2016-06-30 17:24:44 +02001977 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001978 if (IS_ERR(prog))
1979 return prog;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001980 if (!bpf_prog_get_ok(prog, attach_type, attach_drv)) {
Daniel Borkmann113214b2016-06-30 17:24:44 +02001981 prog = ERR_PTR(-EINVAL);
1982 goto out;
1983 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001984
Andrii Nakryiko85192db2019-11-17 09:28:03 -08001985 bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001986out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001987 fdput(f);
1988 return prog;
1989}
Daniel Borkmann113214b2016-06-30 17:24:44 +02001990
1991struct bpf_prog *bpf_prog_get(u32 ufd)
1992{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001993 return __bpf_prog_get(ufd, NULL, false);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001994}
1995
Jakub Kicinski248f3462017-11-03 13:56:20 -07001996struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001997 bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001998{
Alexei Starovoitov4d220ed2018-04-28 19:56:37 -07001999 return __bpf_prog_get(ufd, &type, attach_drv);
Jakub Kicinski248f3462017-11-03 13:56:20 -07002000}
Jakub Kicinski6c8dfe22017-11-03 13:56:21 -07002001EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
Jakub Kicinski248f3462017-11-03 13:56:20 -07002002
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002003/* Initially all BPF programs could be loaded w/o specifying
2004 * expected_attach_type. Later for some of them specifying expected_attach_type
2005 * at load time became required so that program could be validated properly.
2006 * Programs of types that are allowed to be loaded both w/ and w/o (for
2007 * backward compatibility) expected_attach_type, should have the default attach
2008 * type assigned to expected_attach_type for the latter case, so that it can be
2009 * validated later at attach time.
2010 *
2011 * bpf_prog_load_fixup_attach_type() sets expected_attach_type in @attr if
2012 * prog type requires it but has some attach types that have to be backward
2013 * compatible.
2014 */
2015static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
2016{
2017 switch (attr->prog_type) {
2018 case BPF_PROG_TYPE_CGROUP_SOCK:
2019 /* Unfortunately BPF_ATTACH_TYPE_UNSPEC enumeration doesn't
2020 * exist so checking for non-zero is the way to go here.
2021 */
2022 if (!attr->expected_attach_type)
2023 attr->expected_attach_type =
2024 BPF_CGROUP_INET_SOCK_CREATE;
2025 break;
2026 }
2027}
2028
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002029static int
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002030bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
2031 enum bpf_attach_type expected_attach_type,
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002032 u32 btf_id, u32 prog_fd)
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002033{
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002034 if (btf_id) {
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002035 if (btf_id > BTF_MAX_TYPE)
2036 return -EINVAL;
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002037
2038 switch (prog_type) {
2039 case BPF_PROG_TYPE_TRACING:
KP Singh9e4e01d2020-03-29 01:43:52 +01002040 case BPF_PROG_TYPE_LSM:
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002041 case BPF_PROG_TYPE_STRUCT_OPS:
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002042 case BPF_PROG_TYPE_EXT:
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002043 break;
2044 default:
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002045 return -EINVAL;
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002046 }
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002047 }
2048
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002049 if (prog_fd && prog_type != BPF_PROG_TYPE_TRACING &&
2050 prog_type != BPF_PROG_TYPE_EXT)
Martin KaFai Lau27ae79972020-01-08 16:35:03 -08002051 return -EINVAL;
2052
Alexei Starovoitovc108e3c2019-10-17 23:09:33 -07002053 switch (prog_type) {
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002054 case BPF_PROG_TYPE_CGROUP_SOCK:
2055 switch (expected_attach_type) {
2056 case BPF_CGROUP_INET_SOCK_CREATE:
Stanislav Fomichevf5836742020-07-06 16:01:25 -07002057 case BPF_CGROUP_INET_SOCK_RELEASE:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002058 case BPF_CGROUP_INET4_POST_BIND:
2059 case BPF_CGROUP_INET6_POST_BIND:
2060 return 0;
2061 default:
2062 return -EINVAL;
2063 }
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002064 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2065 switch (expected_attach_type) {
2066 case BPF_CGROUP_INET4_BIND:
2067 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07002068 case BPF_CGROUP_INET4_CONNECT:
2069 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02002070 case BPF_CGROUP_INET4_GETPEERNAME:
2071 case BPF_CGROUP_INET6_GETPEERNAME:
2072 case BPF_CGROUP_INET4_GETSOCKNAME:
2073 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07002074 case BPF_CGROUP_UDP4_SENDMSG:
2075 case BPF_CGROUP_UDP6_SENDMSG:
Daniel Borkmann983695f2019-06-07 01:48:57 +02002076 case BPF_CGROUP_UDP4_RECVMSG:
2077 case BPF_CGROUP_UDP6_RECVMSG:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002078 return 0;
2079 default:
2080 return -EINVAL;
2081 }
brakmo5cf1e912019-05-28 16:59:36 -07002082 case BPF_PROG_TYPE_CGROUP_SKB:
2083 switch (expected_attach_type) {
2084 case BPF_CGROUP_INET_INGRESS:
2085 case BPF_CGROUP_INET_EGRESS:
2086 return 0;
2087 default:
2088 return -EINVAL;
2089 }
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07002090 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2091 switch (expected_attach_type) {
2092 case BPF_CGROUP_SETSOCKOPT:
2093 case BPF_CGROUP_GETSOCKOPT:
2094 return 0;
2095 default:
2096 return -EINVAL;
2097 }
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02002098 case BPF_PROG_TYPE_SK_LOOKUP:
2099 if (expected_attach_type == BPF_SK_LOOKUP)
2100 return 0;
2101 return -EINVAL;
Alexei Starovoitovbe8704f2020-01-20 16:53:46 -08002102 case BPF_PROG_TYPE_EXT:
2103 if (expected_attach_type)
2104 return -EINVAL;
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05002105 fallthrough;
Andrey Ignatov4fbac772018-03-30 15:08:02 -07002106 default:
2107 return 0;
2108 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002109}
2110
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002111static bool is_net_admin_prog_type(enum bpf_prog_type prog_type)
2112{
2113 switch (prog_type) {
2114 case BPF_PROG_TYPE_SCHED_CLS:
2115 case BPF_PROG_TYPE_SCHED_ACT:
2116 case BPF_PROG_TYPE_XDP:
2117 case BPF_PROG_TYPE_LWT_IN:
2118 case BPF_PROG_TYPE_LWT_OUT:
2119 case BPF_PROG_TYPE_LWT_XMIT:
2120 case BPF_PROG_TYPE_LWT_SEG6LOCAL:
2121 case BPF_PROG_TYPE_SK_SKB:
2122 case BPF_PROG_TYPE_SK_MSG:
2123 case BPF_PROG_TYPE_LIRC_MODE2:
2124 case BPF_PROG_TYPE_FLOW_DISSECTOR:
2125 case BPF_PROG_TYPE_CGROUP_DEVICE:
2126 case BPF_PROG_TYPE_CGROUP_SOCK:
2127 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
2128 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
2129 case BPF_PROG_TYPE_CGROUP_SYSCTL:
2130 case BPF_PROG_TYPE_SOCK_OPS:
2131 case BPF_PROG_TYPE_EXT: /* extends any prog */
2132 return true;
2133 case BPF_PROG_TYPE_CGROUP_SKB:
2134 /* always unpriv */
2135 case BPF_PROG_TYPE_SK_REUSEPORT:
2136 /* equivalent to SOCKET_FILTER. need CAP_BPF only */
2137 default:
2138 return false;
2139 }
2140}
2141
2142static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
2143{
2144 switch (prog_type) {
2145 case BPF_PROG_TYPE_KPROBE:
2146 case BPF_PROG_TYPE_TRACEPOINT:
2147 case BPF_PROG_TYPE_PERF_EVENT:
2148 case BPF_PROG_TYPE_RAW_TRACEPOINT:
2149 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
2150 case BPF_PROG_TYPE_TRACING:
2151 case BPF_PROG_TYPE_LSM:
2152 case BPF_PROG_TYPE_STRUCT_OPS: /* has access to struct sock */
2153 case BPF_PROG_TYPE_EXT: /* extends any prog */
2154 return true;
2155 default:
2156 return false;
2157 }
2158}
2159
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002160/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002161#define BPF_PROG_LOAD_LAST_FIELD attach_prog_fd
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002162
Yonghong Song838e9692018-11-19 15:29:11 -08002163static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002164{
2165 enum bpf_prog_type type = attr->prog_type;
2166 struct bpf_prog *prog;
2167 int err;
2168 char license[128];
2169 bool is_gpl;
2170
2171 if (CHECK_ATTR(BPF_PROG_LOAD))
2172 return -EINVAL;
2173
Jiong Wangc240eff2019-05-24 23:25:16 +01002174 if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT |
2175 BPF_F_ANY_ALIGNMENT |
Alexei Starovoitov10d274e2019-08-22 22:52:12 -07002176 BPF_F_TEST_STATE_FREQ |
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07002177 BPF_F_SLEEPABLE |
Jiong Wangc240eff2019-05-24 23:25:16 +01002178 BPF_F_TEST_RND_HI32))
David S. Millere07b98d2017-05-10 11:38:07 -07002179 return -EINVAL;
2180
David Millere9ee9ef2018-11-30 21:08:14 -08002181 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
2182 (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002183 !bpf_capable())
David Millere9ee9ef2018-11-30 21:08:14 -08002184 return -EPERM;
2185
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002186 /* copy eBPF program license from user space */
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002187 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002188 sizeof(license) - 1) < 0)
2189 return -EFAULT;
2190 license[sizeof(license) - 1] = 0;
2191
2192 /* eBPF programs must be GPL compatible to use GPL-ed functions */
2193 is_gpl = license_is_gpl_compatible(license);
2194
Alexei Starovoitovc04c0d22019-04-01 21:27:45 -07002195 if (attr->insn_cnt == 0 ||
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002196 attr->insn_cnt > (bpf_capable() ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
Daniel Borkmannef0915c2016-12-07 01:15:44 +01002197 return -E2BIG;
Chenbo Feng80b7d812017-05-31 18:16:00 -07002198 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
2199 type != BPF_PROG_TYPE_CGROUP_SKB &&
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002200 !bpf_capable())
2201 return -EPERM;
2202
Maciej Żenczykowskib338cb92020-06-20 14:26:16 -07002203 if (is_net_admin_prog_type(type) && !capable(CAP_NET_ADMIN) && !capable(CAP_SYS_ADMIN))
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002204 return -EPERM;
2205 if (is_perfmon_prog_type(type) && !perfmon_capable())
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07002206 return -EPERM;
2207
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07002208 bpf_prog_load_fixup_attach_type(attr);
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002209 if (bpf_prog_load_check_attach(type, attr->expected_attach_type,
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002210 attr->attach_btf_id,
2211 attr->attach_prog_fd))
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002212 return -EINVAL;
2213
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002214 /* plain bpf_prog allocation */
2215 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
2216 if (!prog)
2217 return -ENOMEM;
2218
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002219 prog->expected_attach_type = attr->expected_attach_type;
Alexei Starovoitovccfe29e2019-10-15 20:24:58 -07002220 prog->aux->attach_btf_id = attr->attach_btf_id;
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002221 if (attr->attach_prog_fd) {
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002222 struct bpf_prog *dst_prog;
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002223
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002224 dst_prog = bpf_prog_get(attr->attach_prog_fd);
2225 if (IS_ERR(dst_prog)) {
2226 err = PTR_ERR(dst_prog);
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002227 goto free_prog_nouncharge;
2228 }
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002229 prog->aux->dst_prog = dst_prog;
Alexei Starovoitov5b92a282019-11-14 10:57:17 -08002230 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07002231
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002232 prog->aux->offload_requested = !!attr->prog_ifindex;
Alexei Starovoitov1e6c62a2020-08-27 15:01:11 -07002233 prog->aux->sleepable = attr->prog_flags & BPF_F_SLEEPABLE;
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002234
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002235 err = security_bpf_prog_alloc(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002236 if (err)
2237 goto free_prog_nouncharge;
2238
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002239 err = bpf_prog_charge_memlock(prog);
2240 if (err)
2241 goto free_prog_sec;
2242
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002243 prog->len = attr->insn_cnt;
2244
2245 err = -EFAULT;
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002246 if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns),
Daniel Borkmannaafe6ae2016-12-18 01:52:57 +01002247 bpf_prog_insn_size(prog)) != 0)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002248 goto free_prog;
2249
2250 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +02002251 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002252
Andrii Nakryiko85192db2019-11-17 09:28:03 -08002253 atomic64_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +02002254 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002255
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08002256 if (bpf_prog_is_dev_bound(prog->aux)) {
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07002257 err = bpf_prog_offload_init(prog, attr);
2258 if (err)
2259 goto free_prog;
2260 }
2261
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002262 /* find program type: socket_filter vs tracing_filter */
2263 err = find_prog_type(type, prog);
2264 if (err < 0)
2265 goto free_prog;
2266
Jason A. Donenfeld9285ec42019-06-21 22:32:48 +02002267 prog->aux->load_time = ktime_get_boottime_ns();
Martin KaFai Lau8e7ae252020-03-13 18:02:09 -07002268 err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
2269 sizeof(attr->prog_name));
2270 if (err < 0)
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07002271 goto free_prog;
2272
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002273 /* run eBPF verifier */
Yonghong Song838e9692018-11-19 15:29:11 -08002274 err = bpf_check(&prog, attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002275 if (err < 0)
2276 goto free_used_maps;
2277
Daniel Borkmann9facc332018-06-15 02:30:48 +02002278 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61ab2015-05-19 16:59:03 -07002279 if (err < 0)
2280 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002281
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07002282 err = bpf_prog_alloc_id(prog);
2283 if (err)
2284 goto free_used_maps;
2285
Daniel Borkmannc7517982019-08-23 22:14:23 +02002286 /* Upon success of bpf_prog_alloc_id(), the BPF prog is
2287 * effectively publicly exposed. However, retrieving via
2288 * bpf_prog_get_fd_by_id() will take another reference,
2289 * therefore it cannot be gone underneath us.
2290 *
2291 * Only for the time /after/ successful bpf_prog_new_fd()
2292 * and before returning to userspace, we might just hold
2293 * one reference and any parallel close on that fd could
2294 * rip everything out. Hence, below notifications must
2295 * happen before bpf_prog_new_fd().
2296 *
2297 * Also, any failure handling from this point onwards must
2298 * be using bpf_prog_put() given the program is exposed.
2299 */
Daniel Borkmann74451e662017-02-16 22:24:50 +01002300 bpf_prog_kallsyms_add(prog);
Song Liu6ee52e22019-01-17 08:15:15 -08002301 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
Daniel Borkmannbae141f2019-12-06 22:49:34 +01002302 bpf_audit_prog(prog, BPF_AUDIT_LOAD);
Daniel Borkmannc7517982019-08-23 22:14:23 +02002303
2304 err = bpf_prog_new_fd(prog);
2305 if (err < 0)
2306 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002307 return err;
2308
2309free_used_maps:
Daniel Borkmanncd7455f2019-10-22 15:57:23 +02002310 /* In case we have subprogs, we need to wait for a grace
2311 * period before we can tear down JIT memory since symbols
2312 * are already exposed under kallsyms.
2313 */
2314 __bpf_prog_put_noref(prog, prog->aux->func_cnt);
2315 return err;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002316free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002317 bpf_prog_uncharge_memlock(prog);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002318free_prog_sec:
2319 security_bpf_prog_free(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07002320free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002321 bpf_prog_free(prog);
2322 return err;
2323}
2324
Chenbo Feng6e71b042017-10-18 13:00:22 -07002325#define BPF_OBJ_LAST_FIELD file_flags
Daniel Borkmannb2197752015-10-29 14:58:09 +01002326
2327static int bpf_obj_pin(const union bpf_attr *attr)
2328{
Chenbo Feng6e71b042017-10-18 13:00:22 -07002329 if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
Daniel Borkmannb2197752015-10-29 14:58:09 +01002330 return -EINVAL;
2331
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01002332 return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +01002333}
2334
2335static int bpf_obj_get(const union bpf_attr *attr)
2336{
Chenbo Feng6e71b042017-10-18 13:00:22 -07002337 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 ||
2338 attr->file_flags & ~BPF_OBJ_FLAG_MASK)
Daniel Borkmannb2197752015-10-29 14:58:09 +01002339 return -EINVAL;
2340
Chenbo Feng6e71b042017-10-18 13:00:22 -07002341 return bpf_obj_get_user(u64_to_user_ptr(attr->pathname),
2342 attr->file_flags);
Daniel Borkmannb2197752015-10-29 14:58:09 +01002343}
2344
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002345void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002346 const struct bpf_link_ops *ops, struct bpf_prog *prog)
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002347{
2348 atomic64_set(&link->refcnt, 1);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002349 link->type = type;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002350 link->id = 0;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002351 link->ops = ops;
2352 link->prog = prog;
2353}
2354
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002355static void bpf_link_free_id(int id)
2356{
2357 if (!id)
2358 return;
2359
2360 spin_lock_bh(&link_idr_lock);
2361 idr_remove(&link_idr, id);
2362 spin_unlock_bh(&link_idr_lock);
2363}
2364
Andrii Nakryiko98868662020-03-12 17:21:28 -07002365/* Clean up bpf_link and corresponding anon_inode file and FD. After
2366 * anon_inode is created, bpf_link can't be just kfree()'d due to deferred
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002367 * anon_inode's release() call. This helper marksbpf_link as
2368 * defunct, releases anon_inode file and puts reserved FD. bpf_prog's refcnt
2369 * is not decremented, it's the responsibility of a calling code that failed
2370 * to complete bpf_link initialization.
Andrii Nakryiko98868662020-03-12 17:21:28 -07002371 */
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002372void bpf_link_cleanup(struct bpf_link_primer *primer)
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002373{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002374 primer->link->prog = NULL;
2375 bpf_link_free_id(primer->id);
2376 fput(primer->file);
2377 put_unused_fd(primer->fd);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002378}
2379
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002380void bpf_link_inc(struct bpf_link *link)
2381{
2382 atomic64_inc(&link->refcnt);
2383}
2384
2385/* bpf_link_free is guaranteed to be called from process context */
2386static void bpf_link_free(struct bpf_link *link)
2387{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002388 bpf_link_free_id(link->id);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002389 if (link->prog) {
2390 /* detach BPF program, clean up used resources */
2391 link->ops->release(link);
2392 bpf_prog_put(link->prog);
2393 }
2394 /* free bpf_link and its containing memory */
2395 link->ops->dealloc(link);
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002396}
2397
2398static void bpf_link_put_deferred(struct work_struct *work)
2399{
2400 struct bpf_link *link = container_of(work, struct bpf_link, work);
2401
2402 bpf_link_free(link);
2403}
2404
2405/* bpf_link_put can be called from atomic context, but ensures that resources
2406 * are freed from process context
2407 */
2408void bpf_link_put(struct bpf_link *link)
2409{
2410 if (!atomic64_dec_and_test(&link->refcnt))
2411 return;
2412
Alexei Starovoitovf00f2f72020-09-23 19:10:38 -07002413 if (in_atomic()) {
2414 INIT_WORK(&link->work, bpf_link_put_deferred);
2415 schedule_work(&link->work);
2416 } else {
2417 bpf_link_free(link);
2418 }
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002419}
2420
2421static int bpf_link_release(struct inode *inode, struct file *filp)
2422{
2423 struct bpf_link *link = filp->private_data;
2424
2425 bpf_link_put(link);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002426 return 0;
2427}
2428
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002429#ifdef CONFIG_PROC_FS
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002430#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
2431#define BPF_MAP_TYPE(_id, _ops)
2432#define BPF_LINK_TYPE(_id, _name) [_id] = #_name,
2433static const char *bpf_link_type_strs[] = {
2434 [BPF_LINK_TYPE_UNSPEC] = "<invalid>",
2435#include <linux/bpf_types.h>
2436};
2437#undef BPF_PROG_TYPE
2438#undef BPF_MAP_TYPE
2439#undef BPF_LINK_TYPE
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002440
2441static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
2442{
2443 const struct bpf_link *link = filp->private_data;
2444 const struct bpf_prog *prog = link->prog;
2445 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002446
2447 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
2448 seq_printf(m,
2449 "link_type:\t%s\n"
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002450 "link_id:\t%u\n"
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002451 "prog_tag:\t%s\n"
2452 "prog_id:\t%u\n",
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002453 bpf_link_type_strs[link->type],
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002454 link->id,
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002455 prog_tag,
2456 prog->aux->id);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002457 if (link->ops->show_fdinfo)
2458 link->ops->show_fdinfo(link, m);
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002459}
2460#endif
2461
Zou Wei6f302bf2020-04-23 10:32:40 +08002462static const struct file_operations bpf_link_fops = {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002463#ifdef CONFIG_PROC_FS
2464 .show_fdinfo = bpf_link_show_fdinfo,
2465#endif
2466 .release = bpf_link_release,
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002467 .read = bpf_dummy_read,
2468 .write = bpf_dummy_write,
2469};
2470
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002471static int bpf_link_alloc_id(struct bpf_link *link)
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002472{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002473 int id;
2474
2475 idr_preload(GFP_KERNEL);
2476 spin_lock_bh(&link_idr_lock);
2477 id = idr_alloc_cyclic(&link_idr, link, 1, INT_MAX, GFP_ATOMIC);
2478 spin_unlock_bh(&link_idr_lock);
2479 idr_preload_end();
2480
2481 return id;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002482}
2483
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002484/* Prepare bpf_link to be exposed to user-space by allocating anon_inode file,
2485 * reserving unused FD and allocating ID from link_idr. This is to be paired
2486 * with bpf_link_settle() to install FD and ID and expose bpf_link to
2487 * user-space, if bpf_link is successfully attached. If not, bpf_link and
2488 * pre-allocated resources are to be freed with bpf_cleanup() call. All the
2489 * transient state is passed around in struct bpf_link_primer.
2490 * This is preferred way to create and initialize bpf_link, especially when
2491 * there are complicated and expensive operations inbetween creating bpf_link
2492 * itself and attaching it to BPF hook. By using bpf_link_prime() and
2493 * bpf_link_settle() kernel code using bpf_link doesn't have to perform
2494 * expensive (and potentially failing) roll back operations in a rare case
2495 * that file, FD, or ID can't be allocated.
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002496 */
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002497int bpf_link_prime(struct bpf_link *link, struct bpf_link_primer *primer)
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002498{
2499 struct file *file;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002500 int fd, id;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002501
2502 fd = get_unused_fd_flags(O_CLOEXEC);
2503 if (fd < 0)
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002504 return fd;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002505
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002506
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002507 id = bpf_link_alloc_id(link);
2508 if (id < 0) {
2509 put_unused_fd(fd);
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002510 return id;
2511 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002512
2513 file = anon_inode_getfile("bpf_link", &bpf_link_fops, link, O_CLOEXEC);
2514 if (IS_ERR(file)) {
Andrii Nakryiko138c6762020-05-01 11:56:22 -07002515 bpf_link_free_id(id);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002516 put_unused_fd(fd);
Andrii Nakryiko138c6762020-05-01 11:56:22 -07002517 return PTR_ERR(file);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002518 }
2519
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002520 primer->link = link;
2521 primer->file = file;
2522 primer->fd = fd;
2523 primer->id = id;
2524 return 0;
2525}
2526
2527int bpf_link_settle(struct bpf_link_primer *primer)
2528{
2529 /* make bpf_link fetchable by ID */
2530 spin_lock_bh(&link_idr_lock);
2531 primer->link->id = primer->id;
2532 spin_unlock_bh(&link_idr_lock);
2533 /* make bpf_link fetchable by FD */
2534 fd_install(primer->fd, primer->file);
2535 /* pass through installed FD */
2536 return primer->fd;
2537}
2538
2539int bpf_link_new_fd(struct bpf_link *link)
2540{
2541 return anon_inode_getfd("bpf-link", &bpf_link_fops, link, O_CLOEXEC);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002542}
2543
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002544struct bpf_link *bpf_link_get_from_fd(u32 ufd)
2545{
2546 struct fd f = fdget(ufd);
2547 struct bpf_link *link;
2548
2549 if (!f.file)
2550 return ERR_PTR(-EBADF);
2551 if (f.file->f_op != &bpf_link_fops) {
2552 fdput(f);
2553 return ERR_PTR(-EINVAL);
2554 }
2555
2556 link = f.file->private_data;
2557 bpf_link_inc(link);
2558 fdput(f);
2559
2560 return link;
2561}
2562
2563struct bpf_tracing_link {
2564 struct bpf_link link;
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002565 enum bpf_attach_type attach_type;
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002566 struct bpf_trampoline *trampoline;
2567 struct bpf_prog *tgt_prog;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002568};
2569
2570static void bpf_tracing_link_release(struct bpf_link *link)
2571{
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002572 struct bpf_tracing_link *tr_link =
2573 container_of(link, struct bpf_tracing_link, link);
2574
2575 WARN_ON_ONCE(bpf_trampoline_unlink_prog(link->prog,
2576 tr_link->trampoline));
2577
2578 bpf_trampoline_put(tr_link->trampoline);
2579
2580 /* tgt_prog is NULL if target is a kernel function */
2581 if (tr_link->tgt_prog)
2582 bpf_prog_put(tr_link->tgt_prog);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002583}
2584
2585static void bpf_tracing_link_dealloc(struct bpf_link *link)
2586{
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002587 struct bpf_tracing_link *tr_link =
2588 container_of(link, struct bpf_tracing_link, link);
2589
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002590 kfree(tr_link);
2591}
2592
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002593static void bpf_tracing_link_show_fdinfo(const struct bpf_link *link,
2594 struct seq_file *seq)
2595{
2596 struct bpf_tracing_link *tr_link =
2597 container_of(link, struct bpf_tracing_link, link);
2598
2599 seq_printf(seq,
2600 "attach_type:\t%d\n",
2601 tr_link->attach_type);
2602}
2603
2604static int bpf_tracing_link_fill_link_info(const struct bpf_link *link,
2605 struct bpf_link_info *info)
2606{
2607 struct bpf_tracing_link *tr_link =
2608 container_of(link, struct bpf_tracing_link, link);
2609
2610 info->tracing.attach_type = tr_link->attach_type;
2611
2612 return 0;
2613}
2614
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002615static const struct bpf_link_ops bpf_tracing_link_lops = {
2616 .release = bpf_tracing_link_release,
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002617 .dealloc = bpf_tracing_link_dealloc,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002618 .show_fdinfo = bpf_tracing_link_show_fdinfo,
2619 .fill_link_info = bpf_tracing_link_fill_link_info,
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002620};
2621
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002622static int bpf_tracing_prog_attach(struct bpf_prog *prog,
2623 int tgt_prog_fd,
2624 u32 btf_id)
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002625{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002626 struct bpf_link_primer link_primer;
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002627 struct bpf_prog *tgt_prog = NULL;
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002628 struct bpf_trampoline *tr = NULL;
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002629 struct bpf_tracing_link *link;
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002630 u64 key = 0;
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002631 int err;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002632
KP Singh9e4e01d2020-03-29 01:43:52 +01002633 switch (prog->type) {
2634 case BPF_PROG_TYPE_TRACING:
2635 if (prog->expected_attach_type != BPF_TRACE_FENTRY &&
2636 prog->expected_attach_type != BPF_TRACE_FEXIT &&
2637 prog->expected_attach_type != BPF_MODIFY_RETURN) {
2638 err = -EINVAL;
2639 goto out_put_prog;
2640 }
2641 break;
2642 case BPF_PROG_TYPE_EXT:
2643 if (prog->expected_attach_type != 0) {
2644 err = -EINVAL;
2645 goto out_put_prog;
2646 }
2647 break;
2648 case BPF_PROG_TYPE_LSM:
2649 if (prog->expected_attach_type != BPF_LSM_MAC) {
2650 err = -EINVAL;
2651 goto out_put_prog;
2652 }
2653 break;
2654 default:
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002655 err = -EINVAL;
2656 goto out_put_prog;
2657 }
2658
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002659 if (!!tgt_prog_fd != !!btf_id) {
2660 err = -EINVAL;
2661 goto out_put_prog;
2662 }
2663
2664 if (tgt_prog_fd) {
2665 /* For now we only allow new targets for BPF_PROG_TYPE_EXT */
2666 if (prog->type != BPF_PROG_TYPE_EXT) {
2667 err = -EINVAL;
2668 goto out_put_prog;
2669 }
2670
2671 tgt_prog = bpf_prog_get(tgt_prog_fd);
2672 if (IS_ERR(tgt_prog)) {
2673 err = PTR_ERR(tgt_prog);
2674 tgt_prog = NULL;
2675 goto out_put_prog;
2676 }
2677
2678 key = bpf_trampoline_compute_key(tgt_prog, btf_id);
2679 }
2680
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002681 link = kzalloc(sizeof(*link), GFP_USER);
2682 if (!link) {
2683 err = -ENOMEM;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002684 goto out_put_prog;
2685 }
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002686 bpf_link_init(&link->link, BPF_LINK_TYPE_TRACING,
2687 &bpf_tracing_link_lops, prog);
2688 link->attach_type = prog->expected_attach_type;
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002689
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002690 mutex_lock(&prog->aux->dst_mutex);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002691
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002692 /* There are a few possible cases here:
2693 *
2694 * - if prog->aux->dst_trampoline is set, the program was just loaded
2695 * and not yet attached to anything, so we can use the values stored
2696 * in prog->aux
2697 *
2698 * - if prog->aux->dst_trampoline is NULL, the program has already been
2699 * attached to a target and its initial target was cleared (below)
2700 *
2701 * - if tgt_prog != NULL, the caller specified tgt_prog_fd +
2702 * target_btf_id using the link_create API.
2703 *
2704 * - if tgt_prog == NULL when this function was called using the old
2705 * raw_tracepoint_open API, and we need a target from prog->aux
2706 *
2707 * The combination of no saved target in prog->aux, and no target
2708 * specified on load is illegal, and we reject that here.
2709 */
2710 if (!prog->aux->dst_trampoline && !tgt_prog) {
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002711 err = -ENOENT;
2712 goto out_unlock;
2713 }
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002714
2715 if (!prog->aux->dst_trampoline ||
2716 (key && key != prog->aux->dst_trampoline->key)) {
2717 /* If there is no saved target, or the specified target is
2718 * different from the destination specified at load time, we
2719 * need a new trampoline and a check for compatibility
2720 */
2721 struct bpf_attach_target_info tgt_info = {};
2722
2723 err = bpf_check_attach_target(NULL, prog, tgt_prog, btf_id,
2724 &tgt_info);
2725 if (err)
2726 goto out_unlock;
2727
2728 tr = bpf_trampoline_get(key, &tgt_info);
2729 if (!tr) {
2730 err = -ENOMEM;
2731 goto out_unlock;
2732 }
2733 } else {
2734 /* The caller didn't specify a target, or the target was the
2735 * same as the destination supplied during program load. This
2736 * means we can reuse the trampoline and reference from program
2737 * load time, and there is no need to allocate a new one. This
2738 * can only happen once for any program, as the saved values in
2739 * prog->aux are cleared below.
2740 */
2741 tr = prog->aux->dst_trampoline;
2742 tgt_prog = prog->aux->dst_prog;
2743 }
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002744
2745 err = bpf_link_prime(&link->link, &link_primer);
2746 if (err)
2747 goto out_unlock;
2748
2749 err = bpf_trampoline_link_prog(prog, tr);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002750 if (err) {
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002751 bpf_link_cleanup(&link_primer);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002752 link = NULL;
2753 goto out_unlock;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002754 }
2755
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002756 link->tgt_prog = tgt_prog;
2757 link->trampoline = tr;
2758
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002759 /* Always clear the trampoline and target prog from prog->aux to make
2760 * sure the original attach destination is not kept alive after a
2761 * program is (re-)attached to another target.
2762 */
2763 if (prog->aux->dst_prog &&
2764 (tgt_prog_fd || tr != prog->aux->dst_trampoline))
2765 /* got extra prog ref from syscall, or attaching to different prog */
2766 bpf_prog_put(prog->aux->dst_prog);
2767 if (prog->aux->dst_trampoline && tr != prog->aux->dst_trampoline)
2768 /* we allocated a new trampoline, so free the old one */
2769 bpf_trampoline_put(prog->aux->dst_trampoline);
2770
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002771 prog->aux->dst_prog = NULL;
2772 prog->aux->dst_trampoline = NULL;
2773 mutex_unlock(&prog->aux->dst_mutex);
2774
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002775 return bpf_link_settle(&link_primer);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002776out_unlock:
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002777 if (tr && tr != prog->aux->dst_trampoline)
2778 bpf_trampoline_put(tr);
Toke Høiland-Jørgensen3aac1ea2020-09-29 14:45:50 +02002779 mutex_unlock(&prog->aux->dst_mutex);
2780 kfree(link);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002781out_put_prog:
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002782 if (tgt_prog_fd && tgt_prog)
2783 bpf_prog_put(tgt_prog);
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002784 bpf_prog_put(prog);
2785 return err;
2786}
2787
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002788struct bpf_raw_tp_link {
2789 struct bpf_link link;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002790 struct bpf_raw_event_map *btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002791};
2792
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002793static void bpf_raw_tp_link_release(struct bpf_link *link)
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002794{
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002795 struct bpf_raw_tp_link *raw_tp =
2796 container_of(link, struct bpf_raw_tp_link, link);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002797
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002798 bpf_probe_unregister(raw_tp->btp, raw_tp->link.prog);
Matt Mullinsa38d1102018-12-12 16:42:37 -08002799 bpf_put_raw_tracepoint(raw_tp->btp);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002800}
2801
2802static void bpf_raw_tp_link_dealloc(struct bpf_link *link)
2803{
2804 struct bpf_raw_tp_link *raw_tp =
2805 container_of(link, struct bpf_raw_tp_link, link);
2806
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002807 kfree(raw_tp);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002808}
2809
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002810static void bpf_raw_tp_link_show_fdinfo(const struct bpf_link *link,
2811 struct seq_file *seq)
2812{
2813 struct bpf_raw_tp_link *raw_tp_link =
2814 container_of(link, struct bpf_raw_tp_link, link);
2815
2816 seq_printf(seq,
2817 "tp_name:\t%s\n",
2818 raw_tp_link->btp->tp->name);
2819}
2820
2821static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link,
2822 struct bpf_link_info *info)
2823{
2824 struct bpf_raw_tp_link *raw_tp_link =
2825 container_of(link, struct bpf_raw_tp_link, link);
2826 char __user *ubuf = u64_to_user_ptr(info->raw_tracepoint.tp_name);
2827 const char *tp_name = raw_tp_link->btp->tp->name;
2828 u32 ulen = info->raw_tracepoint.tp_name_len;
2829 size_t tp_len = strlen(tp_name);
2830
Yonghong Songb4749592020-08-21 12:10:54 -07002831 if (!ulen ^ !ubuf)
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002832 return -EINVAL;
2833
2834 info->raw_tracepoint.tp_name_len = tp_len + 1;
2835
2836 if (!ubuf)
2837 return 0;
2838
2839 if (ulen >= tp_len + 1) {
2840 if (copy_to_user(ubuf, tp_name, tp_len + 1))
2841 return -EFAULT;
2842 } else {
2843 char zero = '\0';
2844
2845 if (copy_to_user(ubuf, tp_name, ulen - 1))
2846 return -EFAULT;
2847 if (put_user(zero, ubuf + ulen - 1))
2848 return -EFAULT;
2849 return -ENOSPC;
2850 }
2851
2852 return 0;
2853}
2854
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002855static const struct bpf_link_ops bpf_raw_tp_link_lops = {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08002856 .release = bpf_raw_tp_link_release,
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002857 .dealloc = bpf_raw_tp_link_dealloc,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002858 .show_fdinfo = bpf_raw_tp_link_show_fdinfo,
2859 .fill_link_info = bpf_raw_tp_link_fill_link_info,
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002860};
2861
2862#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
2863
2864static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
2865{
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002866 struct bpf_link_primer link_primer;
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002867 struct bpf_raw_tp_link *link;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002868 struct bpf_raw_event_map *btp;
2869 struct bpf_prog *prog;
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002870 const char *tp_name;
2871 char buf[128];
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002872 int err;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002873
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002874 if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
2875 return -EINVAL;
2876
2877 prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
2878 if (IS_ERR(prog))
2879 return PTR_ERR(prog);
2880
KP Singh9e4e01d2020-03-29 01:43:52 +01002881 switch (prog->type) {
2882 case BPF_PROG_TYPE_TRACING:
2883 case BPF_PROG_TYPE_EXT:
2884 case BPF_PROG_TYPE_LSM:
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002885 if (attr->raw_tracepoint.name) {
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002886 /* The attach point for this category of programs
2887 * should be specified via btf_id during program load.
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002888 */
2889 err = -EINVAL;
2890 goto out_put_prog;
2891 }
KP Singh9e4e01d2020-03-29 01:43:52 +01002892 if (prog->type == BPF_PROG_TYPE_TRACING &&
2893 prog->expected_attach_type == BPF_TRACE_RAW_TP) {
Alexei Starovoitovfec56f52019-11-14 10:57:04 -08002894 tp_name = prog->aux->attach_func_name;
KP Singh9e4e01d2020-03-29 01:43:52 +01002895 break;
2896 }
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02002897 return bpf_tracing_prog_attach(prog, 0, 0);
KP Singh9e4e01d2020-03-29 01:43:52 +01002898 case BPF_PROG_TYPE_RAW_TRACEPOINT:
2899 case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002900 if (strncpy_from_user(buf,
2901 u64_to_user_ptr(attr->raw_tracepoint.name),
2902 sizeof(buf) - 1) < 0) {
2903 err = -EFAULT;
2904 goto out_put_prog;
2905 }
2906 buf[sizeof(buf) - 1] = 0;
2907 tp_name = buf;
KP Singh9e4e01d2020-03-29 01:43:52 +01002908 break;
2909 default:
2910 err = -EINVAL;
2911 goto out_put_prog;
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002912 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002913
Matt Mullinsa38d1102018-12-12 16:42:37 -08002914 btp = bpf_get_raw_tracepoint(tp_name);
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002915 if (!btp) {
2916 err = -ENOENT;
2917 goto out_put_prog;
2918 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002919
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002920 link = kzalloc(sizeof(*link), GFP_USER);
2921 if (!link) {
Matt Mullinsa38d1102018-12-12 16:42:37 -08002922 err = -ENOMEM;
2923 goto out_put_btp;
2924 }
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07002925 bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT,
2926 &bpf_raw_tp_link_lops, prog);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002927 link->btp = btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002928
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002929 err = bpf_link_prime(&link->link, &link_primer);
2930 if (err) {
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002931 kfree(link);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002932 goto out_put_btp;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002933 }
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002934
2935 err = bpf_probe_register(link->btp, prog);
2936 if (err) {
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002937 bpf_link_cleanup(&link_primer);
Andrii Nakryikobabf3162020-03-09 16:10:51 -07002938 goto out_put_btp;
2939 }
2940
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07002941 return bpf_link_settle(&link_primer);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002942
Matt Mullinsa38d1102018-12-12 16:42:37 -08002943out_put_btp:
2944 bpf_put_raw_tracepoint(btp);
Alexei Starovoitovac4414b2019-10-15 20:25:01 -07002945out_put_prog:
2946 bpf_prog_put(prog);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002947 return err;
2948}
2949
Anders Roxell33491582018-04-03 14:09:47 +02002950static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
2951 enum bpf_attach_type attach_type)
2952{
2953 switch (prog->type) {
2954 case BPF_PROG_TYPE_CGROUP_SOCK:
2955 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07002956 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02002957 case BPF_PROG_TYPE_SK_LOOKUP:
Anders Roxell33491582018-04-03 14:09:47 +02002958 return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
brakmo5cf1e912019-05-28 16:59:36 -07002959 case BPF_PROG_TYPE_CGROUP_SKB:
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07002960 if (!capable(CAP_NET_ADMIN))
2961 /* cg-skb progs can be loaded by unpriv user.
2962 * check permissions at attach time.
2963 */
2964 return -EPERM;
brakmo5cf1e912019-05-28 16:59:36 -07002965 return prog->enforce_expected_attach_type &&
2966 prog->expected_attach_type != attach_type ?
2967 -EINVAL : 0;
Anders Roxell33491582018-04-03 14:09:47 +02002968 default:
2969 return 0;
2970 }
2971}
2972
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002973static enum bpf_prog_type
2974attach_type_to_prog_type(enum bpf_attach_type attach_type)
2975{
2976 switch (attach_type) {
2977 case BPF_CGROUP_INET_INGRESS:
2978 case BPF_CGROUP_INET_EGRESS:
2979 return BPF_PROG_TYPE_CGROUP_SKB;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002980 case BPF_CGROUP_INET_SOCK_CREATE:
Stanislav Fomichevf5836742020-07-06 16:01:25 -07002981 case BPF_CGROUP_INET_SOCK_RELEASE:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002982 case BPF_CGROUP_INET4_POST_BIND:
2983 case BPF_CGROUP_INET6_POST_BIND:
2984 return BPF_PROG_TYPE_CGROUP_SOCK;
2985 case BPF_CGROUP_INET4_BIND:
2986 case BPF_CGROUP_INET6_BIND:
2987 case BPF_CGROUP_INET4_CONNECT:
2988 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02002989 case BPF_CGROUP_INET4_GETPEERNAME:
2990 case BPF_CGROUP_INET6_GETPEERNAME:
2991 case BPF_CGROUP_INET4_GETSOCKNAME:
2992 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07002993 case BPF_CGROUP_UDP4_SENDMSG:
2994 case BPF_CGROUP_UDP6_SENDMSG:
2995 case BPF_CGROUP_UDP4_RECVMSG:
2996 case BPF_CGROUP_UDP6_RECVMSG:
2997 return BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
2998 case BPF_CGROUP_SOCK_OPS:
2999 return BPF_PROG_TYPE_SOCK_OPS;
3000 case BPF_CGROUP_DEVICE:
3001 return BPF_PROG_TYPE_CGROUP_DEVICE;
3002 case BPF_SK_MSG_VERDICT:
3003 return BPF_PROG_TYPE_SK_MSG;
3004 case BPF_SK_SKB_STREAM_PARSER:
3005 case BPF_SK_SKB_STREAM_VERDICT:
3006 return BPF_PROG_TYPE_SK_SKB;
3007 case BPF_LIRC_MODE2:
3008 return BPF_PROG_TYPE_LIRC_MODE2;
3009 case BPF_FLOW_DISSECTOR:
3010 return BPF_PROG_TYPE_FLOW_DISSECTOR;
3011 case BPF_CGROUP_SYSCTL:
3012 return BPF_PROG_TYPE_CGROUP_SYSCTL;
3013 case BPF_CGROUP_GETSOCKOPT:
3014 case BPF_CGROUP_SETSOCKOPT:
3015 return BPF_PROG_TYPE_CGROUP_SOCKOPT;
Yonghong Songde4e05c2020-05-09 10:59:01 -07003016 case BPF_TRACE_ITER:
3017 return BPF_PROG_TYPE_TRACING;
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02003018 case BPF_SK_LOOKUP:
3019 return BPF_PROG_TYPE_SK_LOOKUP;
Andrii Nakryikoaa8d3a72020-07-21 23:45:57 -07003020 case BPF_XDP:
3021 return BPF_PROG_TYPE_XDP;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003022 default:
3023 return BPF_PROG_TYPE_UNSPEC;
3024 }
3025}
3026
Andrey Ignatov7dd68b32019-12-18 23:44:35 -08003027#define BPF_PROG_ATTACH_LAST_FIELD replace_bpf_fd
John Fastabend174a79f2017-08-15 22:32:47 -07003028
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003029#define BPF_F_ATTACH_MASK \
Andrey Ignatov7dd68b32019-12-18 23:44:35 -08003030 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI | BPF_F_REPLACE)
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003031
Daniel Mackf4324552016-11-23 16:52:27 +01003032static int bpf_prog_attach(const union bpf_attr *attr)
3033{
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003034 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01003035 struct bpf_prog *prog;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003036 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01003037
Daniel Mackf4324552016-11-23 16:52:27 +01003038 if (CHECK_ATTR(BPF_PROG_ATTACH))
3039 return -EINVAL;
3040
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003041 if (attr->attach_flags & ~BPF_F_ATTACH_MASK)
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003042 return -EINVAL;
3043
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003044 ptype = attach_type_to_prog_type(attr->attach_type);
3045 if (ptype == BPF_PROG_TYPE_UNSPEC)
Daniel Mackf4324552016-11-23 16:52:27 +01003046 return -EINVAL;
Daniel Mackf4324552016-11-23 16:52:27 +01003047
David Ahernb2cd1252016-12-01 08:48:03 -08003048 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
3049 if (IS_ERR(prog))
3050 return PTR_ERR(prog);
3051
Andrey Ignatov5e43f892018-03-30 15:08:00 -07003052 if (bpf_prog_attach_check_attach_type(prog, attr->attach_type)) {
3053 bpf_prog_put(prog);
3054 return -EINVAL;
3055 }
3056
Sean Youngfdb5c452018-06-19 00:04:24 +01003057 switch (ptype) {
3058 case BPF_PROG_TYPE_SK_SKB:
3059 case BPF_PROG_TYPE_SK_MSG:
Daniel Borkmann604326b2018-10-13 02:45:58 +02003060 ret = sock_map_get_from_fd(attr, prog);
Sean Youngfdb5c452018-06-19 00:04:24 +01003061 break;
3062 case BPF_PROG_TYPE_LIRC_MODE2:
3063 ret = lirc_prog_attach(attr, prog);
3064 break;
Petar Penkovd58e4682018-09-14 07:46:18 -07003065 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02003066 ret = netns_bpf_prog_attach(attr, prog);
Petar Penkovd58e4682018-09-14 07:46:18 -07003067 break;
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003068 case BPF_PROG_TYPE_CGROUP_DEVICE:
3069 case BPF_PROG_TYPE_CGROUP_SKB:
3070 case BPF_PROG_TYPE_CGROUP_SOCK:
3071 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3072 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3073 case BPF_PROG_TYPE_CGROUP_SYSCTL:
3074 case BPF_PROG_TYPE_SOCK_OPS:
Sean Youngfdb5c452018-06-19 00:04:24 +01003075 ret = cgroup_bpf_prog_attach(attr, ptype, prog);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003076 break;
3077 default:
3078 ret = -EINVAL;
David Ahernb2cd1252016-12-01 08:48:03 -08003079 }
3080
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003081 if (ret)
3082 bpf_prog_put(prog);
Alexei Starovoitov7f677632017-02-10 20:28:24 -08003083 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01003084}
3085
3086#define BPF_PROG_DETACH_LAST_FIELD attach_type
3087
3088static int bpf_prog_detach(const union bpf_attr *attr)
3089{
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07003090 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01003091
Daniel Mackf4324552016-11-23 16:52:27 +01003092 if (CHECK_ATTR(BPF_PROG_DETACH))
3093 return -EINVAL;
3094
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003095 ptype = attach_type_to_prog_type(attr->attach_type);
3096
3097 switch (ptype) {
3098 case BPF_PROG_TYPE_SK_MSG:
3099 case BPF_PROG_TYPE_SK_SKB:
Lorenz Bauerbb0de312020-06-29 10:56:28 +01003100 return sock_map_prog_detach(attr, ptype);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003101 case BPF_PROG_TYPE_LIRC_MODE2:
Sean Youngf4364dc2018-05-27 12:24:09 +01003102 return lirc_prog_detach(attr);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003103 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Lorenz Bauer4ac2add2020-06-29 10:56:26 +01003104 return netns_bpf_prog_detach(attr, ptype);
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003105 case BPF_PROG_TYPE_CGROUP_DEVICE:
3106 case BPF_PROG_TYPE_CGROUP_SKB:
3107 case BPF_PROG_TYPE_CGROUP_SOCK:
3108 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
3109 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
3110 case BPF_PROG_TYPE_CGROUP_SYSCTL:
3111 case BPF_PROG_TYPE_SOCK_OPS:
3112 return cgroup_bpf_prog_detach(attr, ptype);
Daniel Mackf4324552016-11-23 16:52:27 +01003113 default:
3114 return -EINVAL;
3115 }
Daniel Mackf4324552016-11-23 16:52:27 +01003116}
Lawrence Brakmo40304b22017-06-30 20:02:40 -07003117
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003118#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
3119
3120static int bpf_prog_query(const union bpf_attr *attr,
3121 union bpf_attr __user *uattr)
3122{
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003123 if (!capable(CAP_NET_ADMIN))
3124 return -EPERM;
3125 if (CHECK_ATTR(BPF_PROG_QUERY))
3126 return -EINVAL;
3127 if (attr->query.query_flags & ~BPF_F_QUERY_EFFECTIVE)
3128 return -EINVAL;
3129
3130 switch (attr->query.attach_type) {
3131 case BPF_CGROUP_INET_INGRESS:
3132 case BPF_CGROUP_INET_EGRESS:
3133 case BPF_CGROUP_INET_SOCK_CREATE:
Stanislav Fomichevf5836742020-07-06 16:01:25 -07003134 case BPF_CGROUP_INET_SOCK_RELEASE:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07003135 case BPF_CGROUP_INET4_BIND:
3136 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07003137 case BPF_CGROUP_INET4_POST_BIND:
3138 case BPF_CGROUP_INET6_POST_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07003139 case BPF_CGROUP_INET4_CONNECT:
3140 case BPF_CGROUP_INET6_CONNECT:
Daniel Borkmann1b66d252020-05-19 00:45:45 +02003141 case BPF_CGROUP_INET4_GETPEERNAME:
3142 case BPF_CGROUP_INET6_GETPEERNAME:
3143 case BPF_CGROUP_INET4_GETSOCKNAME:
3144 case BPF_CGROUP_INET6_GETSOCKNAME:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07003145 case BPF_CGROUP_UDP4_SENDMSG:
3146 case BPF_CGROUP_UDP6_SENDMSG:
Daniel Borkmann983695f2019-06-07 01:48:57 +02003147 case BPF_CGROUP_UDP4_RECVMSG:
3148 case BPF_CGROUP_UDP6_RECVMSG:
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003149 case BPF_CGROUP_SOCK_OPS:
Roman Gushchinebc614f2017-11-05 08:15:32 -05003150 case BPF_CGROUP_DEVICE:
Andrey Ignatov7b146ce2019-02-27 12:59:24 -08003151 case BPF_CGROUP_SYSCTL:
Stanislav Fomichev0d01da62019-06-27 13:38:47 -07003152 case BPF_CGROUP_GETSOCKOPT:
3153 case BPF_CGROUP_SETSOCKOPT:
Andrii Nakryikoe28784e2020-03-24 23:57:42 -07003154 return cgroup_bpf_prog_query(attr, uattr);
Sean Youngf4364dc2018-05-27 12:24:09 +01003155 case BPF_LIRC_MODE2:
3156 return lirc_prog_query(attr, uattr);
Stanislav Fomichev118c8e92019-04-25 14:37:23 -07003157 case BPF_FLOW_DISSECTOR:
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02003158 case BPF_SK_LOOKUP:
Jakub Sitnickia3fd7ce2020-05-31 10:28:36 +02003159 return netns_bpf_prog_query(attr, uattr);
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003160 default:
3161 return -EINVAL;
3162 }
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07003163}
Daniel Mackf4324552016-11-23 16:52:27 +01003164
Song Liu1b4d60e2020-09-25 13:54:29 -07003165#define BPF_PROG_TEST_RUN_LAST_FIELD test.cpu
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07003166
3167static int bpf_prog_test_run(const union bpf_attr *attr,
3168 union bpf_attr __user *uattr)
3169{
3170 struct bpf_prog *prog;
3171 int ret = -ENOTSUPP;
3172
3173 if (CHECK_ATTR(BPF_PROG_TEST_RUN))
3174 return -EINVAL;
3175
Stanislav Fomichevb0b93952019-04-09 11:49:09 -07003176 if ((attr->test.ctx_size_in && !attr->test.ctx_in) ||
3177 (!attr->test.ctx_size_in && attr->test.ctx_in))
3178 return -EINVAL;
3179
3180 if ((attr->test.ctx_size_out && !attr->test.ctx_out) ||
3181 (!attr->test.ctx_size_out && attr->test.ctx_out))
3182 return -EINVAL;
3183
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07003184 prog = bpf_prog_get(attr->test.prog_fd);
3185 if (IS_ERR(prog))
3186 return PTR_ERR(prog);
3187
3188 if (prog->aux->ops->test_run)
3189 ret = prog->aux->ops->test_run(prog, attr, uattr);
3190
3191 bpf_prog_put(prog);
3192 return ret;
3193}
3194
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07003195#define BPF_OBJ_GET_NEXT_ID_LAST_FIELD next_id
3196
3197static int bpf_obj_get_next_id(const union bpf_attr *attr,
3198 union bpf_attr __user *uattr,
3199 struct idr *idr,
3200 spinlock_t *lock)
3201{
3202 u32 next_id = attr->start_id;
3203 int err = 0;
3204
3205 if (CHECK_ATTR(BPF_OBJ_GET_NEXT_ID) || next_id >= INT_MAX)
3206 return -EINVAL;
3207
3208 if (!capable(CAP_SYS_ADMIN))
3209 return -EPERM;
3210
3211 next_id++;
3212 spin_lock_bh(lock);
3213 if (!idr_get_next(idr, &next_id))
3214 err = -ENOENT;
3215 spin_unlock_bh(lock);
3216
3217 if (!err)
3218 err = put_user(next_id, &uattr->next_id);
3219
3220 return err;
3221}
3222
Yonghong Song6086d292020-05-09 10:59:09 -07003223struct bpf_map *bpf_map_get_curr_or_next(u32 *id)
3224{
3225 struct bpf_map *map;
3226
3227 spin_lock_bh(&map_idr_lock);
3228again:
3229 map = idr_get_next(&map_idr, id);
3230 if (map) {
3231 map = __bpf_map_inc_not_zero(map, false);
3232 if (IS_ERR(map)) {
3233 (*id)++;
3234 goto again;
3235 }
3236 }
3237 spin_unlock_bh(&map_idr_lock);
3238
3239 return map;
3240}
3241
Alexei Starovoitova228a642020-07-01 18:10:18 -07003242struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id)
3243{
3244 struct bpf_prog *prog;
3245
3246 spin_lock_bh(&prog_idr_lock);
3247again:
3248 prog = idr_get_next(&prog_idr, id);
3249 if (prog) {
3250 prog = bpf_prog_inc_not_zero(prog);
3251 if (IS_ERR(prog)) {
3252 (*id)++;
3253 goto again;
3254 }
3255 }
3256 spin_unlock_bh(&prog_idr_lock);
3257
3258 return prog;
3259}
3260
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003261#define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
3262
Björn Töpel7e6897f2019-12-13 18:51:09 +01003263struct bpf_prog *bpf_prog_by_id(u32 id)
3264{
3265 struct bpf_prog *prog;
3266
3267 if (!id)
3268 return ERR_PTR(-ENOENT);
3269
3270 spin_lock_bh(&prog_idr_lock);
3271 prog = idr_find(&prog_idr, id);
3272 if (prog)
3273 prog = bpf_prog_inc_not_zero(prog);
3274 else
3275 prog = ERR_PTR(-ENOENT);
3276 spin_unlock_bh(&prog_idr_lock);
3277 return prog;
3278}
3279
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003280static int bpf_prog_get_fd_by_id(const union bpf_attr *attr)
3281{
3282 struct bpf_prog *prog;
3283 u32 id = attr->prog_id;
3284 int fd;
3285
3286 if (CHECK_ATTR(BPF_PROG_GET_FD_BY_ID))
3287 return -EINVAL;
3288
3289 if (!capable(CAP_SYS_ADMIN))
3290 return -EPERM;
3291
Björn Töpel7e6897f2019-12-13 18:51:09 +01003292 prog = bpf_prog_by_id(id);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07003293 if (IS_ERR(prog))
3294 return PTR_ERR(prog);
3295
3296 fd = bpf_prog_new_fd(prog);
3297 if (fd < 0)
3298 bpf_prog_put(prog);
3299
3300 return fd;
3301}
3302
Chenbo Feng6e71b042017-10-18 13:00:22 -07003303#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD open_flags
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003304
3305static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
3306{
3307 struct bpf_map *map;
3308 u32 id = attr->map_id;
Chenbo Feng6e71b042017-10-18 13:00:22 -07003309 int f_flags;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003310 int fd;
3311
Chenbo Feng6e71b042017-10-18 13:00:22 -07003312 if (CHECK_ATTR(BPF_MAP_GET_FD_BY_ID) ||
3313 attr->open_flags & ~BPF_OBJ_FLAG_MASK)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003314 return -EINVAL;
3315
3316 if (!capable(CAP_SYS_ADMIN))
3317 return -EPERM;
3318
Chenbo Feng6e71b042017-10-18 13:00:22 -07003319 f_flags = bpf_get_file_flag(attr->open_flags);
3320 if (f_flags < 0)
3321 return f_flags;
3322
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003323 spin_lock_bh(&map_idr_lock);
3324 map = idr_find(&map_idr, id);
3325 if (map)
Stanislav Fomichevb0e47012019-08-14 10:37:48 -07003326 map = __bpf_map_inc_not_zero(map, true);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003327 else
3328 map = ERR_PTR(-ENOENT);
3329 spin_unlock_bh(&map_idr_lock);
3330
3331 if (IS_ERR(map))
3332 return PTR_ERR(map);
3333
Chenbo Feng6e71b042017-10-18 13:00:22 -07003334 fd = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003335 if (fd < 0)
Peng Sun781e6282019-02-26 22:15:37 +08003336 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07003337
3338 return fd;
3339}
3340
Daniel Borkmann7105e822017-12-20 13:42:57 +01003341static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003342 unsigned long addr, u32 *off,
3343 u32 *type)
Daniel Borkmann7105e822017-12-20 13:42:57 +01003344{
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003345 const struct bpf_map *map;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003346 int i;
3347
YiFei Zhu984fe942020-09-15 16:45:39 -07003348 mutex_lock(&prog->aux->used_maps_mutex);
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003349 for (i = 0, *off = 0; i < prog->aux->used_map_cnt; i++) {
3350 map = prog->aux->used_maps[i];
3351 if (map == (void *)addr) {
3352 *type = BPF_PSEUDO_MAP_FD;
YiFei Zhu984fe942020-09-15 16:45:39 -07003353 goto out;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003354 }
3355 if (!map->ops->map_direct_value_meta)
3356 continue;
3357 if (!map->ops->map_direct_value_meta(map, addr, off)) {
3358 *type = BPF_PSEUDO_MAP_VALUE;
YiFei Zhu984fe942020-09-15 16:45:39 -07003359 goto out;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003360 }
3361 }
YiFei Zhu984fe942020-09-15 16:45:39 -07003362 map = NULL;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003363
YiFei Zhu984fe942020-09-15 16:45:39 -07003364out:
3365 mutex_unlock(&prog->aux->used_maps_mutex);
3366 return map;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003367}
3368
Kees Cook63960262020-07-02 15:45:23 -07003369static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog,
3370 const struct cred *f_cred)
Daniel Borkmann7105e822017-12-20 13:42:57 +01003371{
3372 const struct bpf_map *map;
3373 struct bpf_insn *insns;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003374 u32 off, type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003375 u64 imm;
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003376 u8 code;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003377 int i;
3378
3379 insns = kmemdup(prog->insnsi, bpf_prog_insn_size(prog),
3380 GFP_USER);
3381 if (!insns)
3382 return insns;
3383
3384 for (i = 0; i < prog->len; i++) {
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003385 code = insns[i].code;
3386
3387 if (code == (BPF_JMP | BPF_TAIL_CALL)) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003388 insns[i].code = BPF_JMP | BPF_CALL;
3389 insns[i].imm = BPF_FUNC_tail_call;
3390 /* fall-through */
3391 }
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003392 if (code == (BPF_JMP | BPF_CALL) ||
3393 code == (BPF_JMP | BPF_CALL_ARGS)) {
3394 if (code == (BPF_JMP | BPF_CALL_ARGS))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003395 insns[i].code = BPF_JMP | BPF_CALL;
Kees Cook63960262020-07-02 15:45:23 -07003396 if (!bpf_dump_raw_ok(f_cred))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003397 insns[i].imm = 0;
3398 continue;
3399 }
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003400 if (BPF_CLASS(code) == BPF_LDX && BPF_MODE(code) == BPF_PROBE_MEM) {
3401 insns[i].code = BPF_LDX | BPF_SIZE(code) | BPF_MEM;
3402 continue;
3403 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01003404
Andrii Nakryiko29fcb052020-06-12 17:21:15 -07003405 if (code != (BPF_LD | BPF_IMM | BPF_DW))
Daniel Borkmann7105e822017-12-20 13:42:57 +01003406 continue;
3407
3408 imm = ((u64)insns[i + 1].imm << 32) | (u32)insns[i].imm;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003409 map = bpf_map_from_imm(prog, imm, &off, &type);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003410 if (map) {
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003411 insns[i].src_reg = type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003412 insns[i].imm = map->id;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02003413 insns[i + 1].imm = off;
Daniel Borkmann7105e822017-12-20 13:42:57 +01003414 continue;
3415 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01003416 }
3417
3418 return insns;
3419}
3420
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003421static int set_info_rec_size(struct bpf_prog_info *info)
3422{
3423 /*
3424 * Ensure info.*_rec_size is the same as kernel expected size
3425 *
3426 * or
3427 *
3428 * Only allow zero *_rec_size if both _rec_size and _cnt are
3429 * zero. In this case, the kernel will set the expected
3430 * _rec_size back to the info.
3431 */
3432
Yonghong Song11d8b822018-12-10 14:14:08 -08003433 if ((info->nr_func_info || info->func_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003434 info->func_info_rec_size != sizeof(struct bpf_func_info))
3435 return -EINVAL;
3436
Yonghong Song11d8b822018-12-10 14:14:08 -08003437 if ((info->nr_line_info || info->line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003438 info->line_info_rec_size != sizeof(struct bpf_line_info))
3439 return -EINVAL;
3440
Yonghong Song11d8b822018-12-10 14:14:08 -08003441 if ((info->nr_jited_line_info || info->jited_line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003442 info->jited_line_info_rec_size != sizeof(__u64))
3443 return -EINVAL;
3444
3445 info->func_info_rec_size = sizeof(struct bpf_func_info);
3446 info->line_info_rec_size = sizeof(struct bpf_line_info);
3447 info->jited_line_info_rec_size = sizeof(__u64);
3448
3449 return 0;
3450}
3451
Kees Cook63960262020-07-02 15:45:23 -07003452static int bpf_prog_get_info_by_fd(struct file *file,
3453 struct bpf_prog *prog,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003454 const union bpf_attr *attr,
3455 union bpf_attr __user *uattr)
3456{
3457 struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003458 struct bpf_prog_info info;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003459 u32 info_len = attr->info.info_len;
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08003460 struct bpf_prog_stats stats;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003461 char __user *uinsns;
3462 u32 ulen;
3463 int err;
3464
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07003465 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003466 if (err)
3467 return err;
3468 info_len = min_t(u32, sizeof(info), info_len);
3469
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003470 memset(&info, 0, sizeof(info));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003471 if (copy_from_user(&info, uinfo, info_len))
Daniel Borkmann89b09682017-07-27 21:02:46 +02003472 return -EFAULT;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003473
3474 info.type = prog->type;
3475 info.id = prog->aux->id;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003476 info.load_time = prog->aux->load_time;
3477 info.created_by_uid = from_kuid_munged(current_user_ns(),
3478 prog->aux->user->uid);
Jiri Olsab85fab02018-04-25 19:41:06 +02003479 info.gpl_compatible = prog->gpl_compatible;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003480
3481 memcpy(info.tag, prog->tag, sizeof(prog->tag));
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003482 memcpy(info.name, prog->aux->name, sizeof(prog->aux->name));
3483
YiFei Zhu984fe942020-09-15 16:45:39 -07003484 mutex_lock(&prog->aux->used_maps_mutex);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003485 ulen = info.nr_map_ids;
3486 info.nr_map_ids = prog->aux->used_map_cnt;
3487 ulen = min_t(u32, info.nr_map_ids, ulen);
3488 if (ulen) {
Martin KaFai Lau721e08d2017-09-29 10:52:17 -07003489 u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003490 u32 i;
3491
3492 for (i = 0; i < ulen; i++)
3493 if (put_user(prog->aux->used_maps[i]->id,
YiFei Zhu984fe942020-09-15 16:45:39 -07003494 &user_map_ids[i])) {
3495 mutex_unlock(&prog->aux->used_maps_mutex);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003496 return -EFAULT;
YiFei Zhu984fe942020-09-15 16:45:39 -07003497 }
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07003498 }
YiFei Zhu984fe942020-09-15 16:45:39 -07003499 mutex_unlock(&prog->aux->used_maps_mutex);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003500
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003501 err = set_info_rec_size(&info);
3502 if (err)
3503 return err;
Martin KaFai Lau73372242018-12-05 17:35:43 -08003504
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08003505 bpf_prog_get_stats(prog, &stats);
3506 info.run_time_ns = stats.nsecs;
3507 info.run_cnt = stats.cnt;
3508
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07003509 if (!bpf_capable()) {
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003510 info.jited_prog_len = 0;
3511 info.xlated_prog_len = 0;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303512 info.nr_jited_ksyms = 0;
Daniel Borkmann28c2fae2018-11-02 11:35:46 +01003513 info.nr_jited_func_lens = 0;
Yonghong Song11d8b822018-12-10 14:14:08 -08003514 info.nr_func_info = 0;
3515 info.nr_line_info = 0;
3516 info.nr_jited_line_info = 0;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003517 goto done;
3518 }
3519
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003520 ulen = info.xlated_prog_len;
Daniel Borkmann9975a542017-07-28 17:05:25 +02003521 info.xlated_prog_len = bpf_prog_insn_size(prog);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003522 if (info.xlated_prog_len && ulen) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003523 struct bpf_insn *insns_sanitized;
3524 bool fault;
3525
Kees Cook63960262020-07-02 15:45:23 -07003526 if (prog->blinded && !bpf_dump_raw_ok(file->f_cred)) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01003527 info.xlated_prog_insns = 0;
3528 goto done;
3529 }
Kees Cook63960262020-07-02 15:45:23 -07003530 insns_sanitized = bpf_insn_prepare_dump(prog, file->f_cred);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003531 if (!insns_sanitized)
3532 return -ENOMEM;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003533 uinsns = u64_to_user_ptr(info.xlated_prog_insns);
3534 ulen = min_t(u32, info.xlated_prog_len, ulen);
Daniel Borkmann7105e822017-12-20 13:42:57 +01003535 fault = copy_to_user(uinsns, insns_sanitized, ulen);
3536 kfree(insns_sanitized);
3537 if (fault)
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003538 return -EFAULT;
3539 }
3540
Jakub Kicinski675fc272017-12-27 18:39:09 -08003541 if (bpf_prog_is_dev_bound(prog->aux)) {
3542 err = bpf_prog_offload_info_fill(&info, prog);
3543 if (err)
3544 return err;
Jiong Wangfcfb1262018-01-16 16:05:19 -08003545 goto done;
3546 }
3547
3548 /* NOTE: the following code is supposed to be skipped for offload.
3549 * bpf_prog_offload_info_fill() is the place to fill similar fields
3550 * for offload.
3551 */
3552 ulen = info.jited_prog_len;
Sandipan Das4d56a762018-05-24 12:26:51 +05303553 if (prog->aux->func_cnt) {
3554 u32 i;
3555
3556 info.jited_prog_len = 0;
3557 for (i = 0; i < prog->aux->func_cnt; i++)
3558 info.jited_prog_len += prog->aux->func[i]->jited_len;
3559 } else {
3560 info.jited_prog_len = prog->jited_len;
3561 }
3562
Jiong Wangfcfb1262018-01-16 16:05:19 -08003563 if (info.jited_prog_len && ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003564 if (bpf_dump_raw_ok(file->f_cred)) {
Jiong Wangfcfb1262018-01-16 16:05:19 -08003565 uinsns = u64_to_user_ptr(info.jited_prog_insns);
3566 ulen = min_t(u32, info.jited_prog_len, ulen);
Sandipan Das4d56a762018-05-24 12:26:51 +05303567
3568 /* for multi-function programs, copy the JITed
3569 * instructions for all the functions
3570 */
3571 if (prog->aux->func_cnt) {
3572 u32 len, free, i;
3573 u8 *img;
3574
3575 free = ulen;
3576 for (i = 0; i < prog->aux->func_cnt; i++) {
3577 len = prog->aux->func[i]->jited_len;
3578 len = min_t(u32, len, free);
3579 img = (u8 *) prog->aux->func[i]->bpf_func;
3580 if (copy_to_user(uinsns, img, len))
3581 return -EFAULT;
3582 uinsns += len;
3583 free -= len;
3584 if (!free)
3585 break;
3586 }
3587 } else {
3588 if (copy_to_user(uinsns, prog->bpf_func, ulen))
3589 return -EFAULT;
3590 }
Jiong Wangfcfb1262018-01-16 16:05:19 -08003591 } else {
3592 info.jited_prog_insns = 0;
3593 }
Jakub Kicinski675fc272017-12-27 18:39:09 -08003594 }
3595
Sandipan Dasdbecd732018-05-24 12:26:48 +05303596 ulen = info.nr_jited_ksyms;
Song Liuff1889f2018-11-02 10:16:17 -07003597 info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08003598 if (ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003599 if (bpf_dump_raw_ok(file->f_cred)) {
Song Liuff1889f2018-11-02 10:16:17 -07003600 unsigned long ksym_addr;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303601 u64 __user *user_ksyms;
Sandipan Dasdbecd732018-05-24 12:26:48 +05303602 u32 i;
3603
3604 /* copy the address of the kernel symbol
3605 * corresponding to each function
3606 */
3607 ulen = min_t(u32, info.nr_jited_ksyms, ulen);
3608 user_ksyms = u64_to_user_ptr(info.jited_ksyms);
Song Liuff1889f2018-11-02 10:16:17 -07003609 if (prog->aux->func_cnt) {
3610 for (i = 0; i < ulen; i++) {
3611 ksym_addr = (unsigned long)
3612 prog->aux->func[i]->bpf_func;
3613 if (put_user((u64) ksym_addr,
3614 &user_ksyms[i]))
3615 return -EFAULT;
3616 }
3617 } else {
3618 ksym_addr = (unsigned long) prog->bpf_func;
3619 if (put_user((u64) ksym_addr, &user_ksyms[0]))
Sandipan Dasdbecd732018-05-24 12:26:48 +05303620 return -EFAULT;
3621 }
3622 } else {
3623 info.jited_ksyms = 0;
3624 }
3625 }
3626
Sandipan Das815581c2018-05-24 12:26:52 +05303627 ulen = info.nr_jited_func_lens;
Song Liuff1889f2018-11-02 10:16:17 -07003628 info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08003629 if (ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003630 if (bpf_dump_raw_ok(file->f_cred)) {
Sandipan Das815581c2018-05-24 12:26:52 +05303631 u32 __user *user_lens;
3632 u32 func_len, i;
3633
3634 /* copy the JITed image lengths for each function */
3635 ulen = min_t(u32, info.nr_jited_func_lens, ulen);
3636 user_lens = u64_to_user_ptr(info.jited_func_lens);
Song Liuff1889f2018-11-02 10:16:17 -07003637 if (prog->aux->func_cnt) {
3638 for (i = 0; i < ulen; i++) {
3639 func_len =
3640 prog->aux->func[i]->jited_len;
3641 if (put_user(func_len, &user_lens[i]))
3642 return -EFAULT;
3643 }
3644 } else {
3645 func_len = prog->jited_len;
3646 if (put_user(func_len, &user_lens[0]))
Sandipan Das815581c2018-05-24 12:26:52 +05303647 return -EFAULT;
3648 }
3649 } else {
3650 info.jited_func_lens = 0;
3651 }
3652 }
3653
Martin KaFai Lau73372242018-12-05 17:35:43 -08003654 if (prog->aux->btf)
Yonghong Song838e9692018-11-19 15:29:11 -08003655 info.btf_id = btf_id(prog->aux->btf);
3656
Yonghong Song11d8b822018-12-10 14:14:08 -08003657 ulen = info.nr_func_info;
3658 info.nr_func_info = prog->aux->func_info_cnt;
3659 if (info.nr_func_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003660 char __user *user_finfo;
Yonghong Song838e9692018-11-19 15:29:11 -08003661
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003662 user_finfo = u64_to_user_ptr(info.func_info);
3663 ulen = min_t(u32, info.nr_func_info, ulen);
3664 if (copy_to_user(user_finfo, prog->aux->func_info,
3665 info.func_info_rec_size * ulen))
3666 return -EFAULT;
Yonghong Song838e9692018-11-19 15:29:11 -08003667 }
3668
Yonghong Song11d8b822018-12-10 14:14:08 -08003669 ulen = info.nr_line_info;
3670 info.nr_line_info = prog->aux->nr_linfo;
3671 if (info.nr_line_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003672 __u8 __user *user_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003673
Martin KaFai Lau9e794162018-12-12 10:18:21 -08003674 user_linfo = u64_to_user_ptr(info.line_info);
3675 ulen = min_t(u32, info.nr_line_info, ulen);
3676 if (copy_to_user(user_linfo, prog->aux->linfo,
3677 info.line_info_rec_size * ulen))
3678 return -EFAULT;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003679 }
3680
Yonghong Song11d8b822018-12-10 14:14:08 -08003681 ulen = info.nr_jited_line_info;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003682 if (prog->aux->jited_linfo)
Yonghong Song11d8b822018-12-10 14:14:08 -08003683 info.nr_jited_line_info = prog->aux->nr_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003684 else
Yonghong Song11d8b822018-12-10 14:14:08 -08003685 info.nr_jited_line_info = 0;
3686 if (info.nr_jited_line_info && ulen) {
Kees Cook63960262020-07-02 15:45:23 -07003687 if (bpf_dump_raw_ok(file->f_cred)) {
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003688 __u64 __user *user_linfo;
3689 u32 i;
3690
3691 user_linfo = u64_to_user_ptr(info.jited_line_info);
Yonghong Song11d8b822018-12-10 14:14:08 -08003692 ulen = min_t(u32, info.nr_jited_line_info, ulen);
Martin KaFai Lauc454a462018-12-07 16:42:25 -08003693 for (i = 0; i < ulen; i++) {
3694 if (put_user((__u64)(long)prog->aux->jited_linfo[i],
3695 &user_linfo[i]))
3696 return -EFAULT;
3697 }
3698 } else {
3699 info.jited_line_info = 0;
3700 }
3701 }
3702
Song Liuc872bdb2018-12-12 09:37:46 -08003703 ulen = info.nr_prog_tags;
3704 info.nr_prog_tags = prog->aux->func_cnt ? : 1;
3705 if (ulen) {
3706 __u8 __user (*user_prog_tags)[BPF_TAG_SIZE];
3707 u32 i;
3708
3709 user_prog_tags = u64_to_user_ptr(info.prog_tags);
3710 ulen = min_t(u32, info.nr_prog_tags, ulen);
3711 if (prog->aux->func_cnt) {
3712 for (i = 0; i < ulen; i++) {
3713 if (copy_to_user(user_prog_tags[i],
3714 prog->aux->func[i]->tag,
3715 BPF_TAG_SIZE))
3716 return -EFAULT;
3717 }
3718 } else {
3719 if (copy_to_user(user_prog_tags[0],
3720 prog->tag, BPF_TAG_SIZE))
3721 return -EFAULT;
3722 }
3723 }
3724
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003725done:
3726 if (copy_to_user(uinfo, &info, info_len) ||
3727 put_user(info_len, &uattr->info.info_len))
3728 return -EFAULT;
3729
3730 return 0;
3731}
3732
Kees Cook63960262020-07-02 15:45:23 -07003733static int bpf_map_get_info_by_fd(struct file *file,
3734 struct bpf_map *map,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003735 const union bpf_attr *attr,
3736 union bpf_attr __user *uattr)
3737{
3738 struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003739 struct bpf_map_info info;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003740 u32 info_len = attr->info.info_len;
3741 int err;
3742
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07003743 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003744 if (err)
3745 return err;
3746 info_len = min_t(u32, sizeof(info), info_len);
3747
Greg Kroah-Hartman5c6f2582020-03-20 17:22:58 +01003748 memset(&info, 0, sizeof(info));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003749 info.type = map->map_type;
3750 info.id = map->id;
3751 info.key_size = map->key_size;
3752 info.value_size = map->value_size;
3753 info.max_entries = map->max_entries;
3754 info.map_flags = map->map_flags;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -07003755 memcpy(info.name, map->name, sizeof(map->name));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003756
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003757 if (map->btf) {
3758 info.btf_id = btf_id(map->btf);
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -07003759 info.btf_key_type_id = map->btf_key_type_id;
3760 info.btf_value_type_id = map->btf_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003761 }
Martin KaFai Lau85d33df2020-01-08 16:35:05 -08003762 info.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003763
Jakub Kicinski52775b32018-01-17 19:13:28 -08003764 if (bpf_map_is_dev_bound(map)) {
3765 err = bpf_map_offload_info_fill(&info, map);
3766 if (err)
3767 return err;
3768 }
3769
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003770 if (copy_to_user(uinfo, &info, info_len) ||
3771 put_user(info_len, &uattr->info.info_len))
3772 return -EFAULT;
3773
3774 return 0;
3775}
3776
Kees Cook63960262020-07-02 15:45:23 -07003777static int bpf_btf_get_info_by_fd(struct file *file,
3778 struct btf *btf,
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003779 const union bpf_attr *attr,
3780 union bpf_attr __user *uattr)
3781{
3782 struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info);
3783 u32 info_len = attr->info.info_len;
3784 int err;
3785
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07003786 err = bpf_check_uarg_tail_zero(uinfo, sizeof(*uinfo), info_len);
Martin KaFai Lau62dab842018-05-04 14:49:52 -07003787 if (err)
3788 return err;
3789
3790 return btf_get_info_by_fd(btf, attr, uattr);
3791}
3792
Kees Cook63960262020-07-02 15:45:23 -07003793static int bpf_link_get_info_by_fd(struct file *file,
3794 struct bpf_link *link,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003795 const union bpf_attr *attr,
3796 union bpf_attr __user *uattr)
3797{
3798 struct bpf_link_info __user *uinfo = u64_to_user_ptr(attr->info.info);
3799 struct bpf_link_info info;
3800 u32 info_len = attr->info.info_len;
3801 int err;
3802
3803 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
3804 if (err)
3805 return err;
3806 info_len = min_t(u32, sizeof(info), info_len);
3807
3808 memset(&info, 0, sizeof(info));
3809 if (copy_from_user(&info, uinfo, info_len))
3810 return -EFAULT;
3811
3812 info.type = link->type;
3813 info.id = link->id;
3814 info.prog_id = link->prog->aux->id;
3815
3816 if (link->ops->fill_link_info) {
3817 err = link->ops->fill_link_info(link, &info);
3818 if (err)
3819 return err;
3820 }
3821
3822 if (copy_to_user(uinfo, &info, info_len) ||
3823 put_user(info_len, &uattr->info.info_len))
3824 return -EFAULT;
3825
3826 return 0;
3827}
3828
3829
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003830#define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info
3831
3832static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
3833 union bpf_attr __user *uattr)
3834{
3835 int ufd = attr->info.bpf_fd;
3836 struct fd f;
3837 int err;
3838
3839 if (CHECK_ATTR(BPF_OBJ_GET_INFO_BY_FD))
3840 return -EINVAL;
3841
3842 f = fdget(ufd);
3843 if (!f.file)
3844 return -EBADFD;
3845
3846 if (f.file->f_op == &bpf_prog_fops)
Kees Cook63960262020-07-02 15:45:23 -07003847 err = bpf_prog_get_info_by_fd(f.file, f.file->private_data, attr,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003848 uattr);
3849 else if (f.file->f_op == &bpf_map_fops)
Kees Cook63960262020-07-02 15:45:23 -07003850 err = bpf_map_get_info_by_fd(f.file, f.file->private_data, attr,
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003851 uattr);
Martin KaFai Lau60197cf2018-04-18 15:56:02 -07003852 else if (f.file->f_op == &btf_fops)
Kees Cook63960262020-07-02 15:45:23 -07003853 err = bpf_btf_get_info_by_fd(f.file, f.file->private_data, attr, uattr);
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003854 else if (f.file->f_op == &bpf_link_fops)
Kees Cook63960262020-07-02 15:45:23 -07003855 err = bpf_link_get_info_by_fd(f.file, f.file->private_data,
Andrii Nakryikof2e10bf2020-04-28 17:16:08 -07003856 attr, uattr);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07003857 else
3858 err = -EINVAL;
3859
3860 fdput(f);
3861 return err;
3862}
3863
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07003864#define BPF_BTF_LOAD_LAST_FIELD btf_log_level
3865
3866static int bpf_btf_load(const union bpf_attr *attr)
3867{
3868 if (CHECK_ATTR(BPF_BTF_LOAD))
3869 return -EINVAL;
3870
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07003871 if (!bpf_capable())
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07003872 return -EPERM;
3873
3874 return btf_new_fd(attr);
3875}
3876
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07003877#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id
3878
3879static int bpf_btf_get_fd_by_id(const union bpf_attr *attr)
3880{
3881 if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID))
3882 return -EINVAL;
3883
3884 if (!capable(CAP_SYS_ADMIN))
3885 return -EPERM;
3886
3887 return btf_get_fd_by_id(attr->btf_id);
3888}
3889
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003890static int bpf_task_fd_query_copy(const union bpf_attr *attr,
3891 union bpf_attr __user *uattr,
3892 u32 prog_id, u32 fd_type,
3893 const char *buf, u64 probe_offset,
3894 u64 probe_addr)
3895{
3896 char __user *ubuf = u64_to_user_ptr(attr->task_fd_query.buf);
3897 u32 len = buf ? strlen(buf) : 0, input_len;
3898 int err = 0;
3899
3900 if (put_user(len, &uattr->task_fd_query.buf_len))
3901 return -EFAULT;
3902 input_len = attr->task_fd_query.buf_len;
3903 if (input_len && ubuf) {
3904 if (!len) {
3905 /* nothing to copy, just make ubuf NULL terminated */
3906 char zero = '\0';
3907
3908 if (put_user(zero, ubuf))
3909 return -EFAULT;
3910 } else if (input_len >= len + 1) {
3911 /* ubuf can hold the string with NULL terminator */
3912 if (copy_to_user(ubuf, buf, len + 1))
3913 return -EFAULT;
3914 } else {
3915 /* ubuf cannot hold the string with NULL terminator,
3916 * do a partial copy with NULL terminator.
3917 */
3918 char zero = '\0';
3919
3920 err = -ENOSPC;
3921 if (copy_to_user(ubuf, buf, input_len - 1))
3922 return -EFAULT;
3923 if (put_user(zero, ubuf + input_len - 1))
3924 return -EFAULT;
3925 }
3926 }
3927
3928 if (put_user(prog_id, &uattr->task_fd_query.prog_id) ||
3929 put_user(fd_type, &uattr->task_fd_query.fd_type) ||
3930 put_user(probe_offset, &uattr->task_fd_query.probe_offset) ||
3931 put_user(probe_addr, &uattr->task_fd_query.probe_addr))
3932 return -EFAULT;
3933
3934 return err;
3935}
3936
3937#define BPF_TASK_FD_QUERY_LAST_FIELD task_fd_query.probe_addr
3938
3939static int bpf_task_fd_query(const union bpf_attr *attr,
3940 union bpf_attr __user *uattr)
3941{
3942 pid_t pid = attr->task_fd_query.pid;
3943 u32 fd = attr->task_fd_query.fd;
3944 const struct perf_event *event;
3945 struct files_struct *files;
3946 struct task_struct *task;
3947 struct file *file;
3948 int err;
3949
3950 if (CHECK_ATTR(BPF_TASK_FD_QUERY))
3951 return -EINVAL;
3952
3953 if (!capable(CAP_SYS_ADMIN))
3954 return -EPERM;
3955
3956 if (attr->task_fd_query.flags != 0)
3957 return -EINVAL;
3958
3959 task = get_pid_task(find_vpid(pid), PIDTYPE_PID);
3960 if (!task)
3961 return -ENOENT;
3962
3963 files = get_files_struct(task);
3964 put_task_struct(task);
3965 if (!files)
3966 return -ENOENT;
3967
3968 err = 0;
3969 spin_lock(&files->file_lock);
3970 file = fcheck_files(files, fd);
3971 if (!file)
3972 err = -EBADF;
3973 else
3974 get_file(file);
3975 spin_unlock(&files->file_lock);
3976 put_files_struct(files);
3977
3978 if (err)
3979 goto out;
3980
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08003981 if (file->f_op == &bpf_link_fops) {
3982 struct bpf_link *link = file->private_data;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003983
Andrii Nakryikoa3b80e12020-04-28 17:16:06 -07003984 if (link->ops == &bpf_raw_tp_link_lops) {
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08003985 struct bpf_raw_tp_link *raw_tp =
3986 container_of(link, struct bpf_raw_tp_link, link);
3987 struct bpf_raw_event_map *btp = raw_tp->btp;
3988
3989 err = bpf_task_fd_query_copy(attr, uattr,
3990 raw_tp->link.prog->aux->id,
3991 BPF_FD_TYPE_RAW_TRACEPOINT,
3992 btp->tp->name, 0, 0);
3993 goto put_file;
3994 }
3995 goto out_not_supp;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07003996 }
3997
3998 event = perf_get_event(file);
3999 if (!IS_ERR(event)) {
4000 u64 probe_offset, probe_addr;
4001 u32 prog_id, fd_type;
4002 const char *buf;
4003
4004 err = bpf_get_perf_event_info(event, &prog_id, &fd_type,
4005 &buf, &probe_offset,
4006 &probe_addr);
4007 if (!err)
4008 err = bpf_task_fd_query_copy(attr, uattr, prog_id,
4009 fd_type, buf,
4010 probe_offset,
4011 probe_addr);
4012 goto put_file;
4013 }
4014
Andrii Nakryiko70ed5062020-03-02 20:31:57 -08004015out_not_supp:
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004016 err = -ENOTSUPP;
4017put_file:
4018 fput(file);
4019out:
4020 return err;
4021}
4022
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004023#define BPF_MAP_BATCH_LAST_FIELD batch.flags
4024
4025#define BPF_DO_BATCH(fn) \
4026 do { \
4027 if (!fn) { \
4028 err = -ENOTSUPP; \
4029 goto err_put; \
4030 } \
4031 err = fn(map, attr, uattr); \
4032 } while (0)
4033
4034static int bpf_map_do_batch(const union bpf_attr *attr,
4035 union bpf_attr __user *uattr,
4036 int cmd)
4037{
4038 struct bpf_map *map;
4039 int err, ufd;
4040 struct fd f;
4041
4042 if (CHECK_ATTR(BPF_MAP_BATCH))
4043 return -EINVAL;
4044
4045 ufd = attr->batch.map_fd;
4046 f = fdget(ufd);
4047 map = __bpf_map_get(f);
4048 if (IS_ERR(map))
4049 return PTR_ERR(map);
4050
Yonghong Song05799632020-01-15 10:43:04 -08004051 if ((cmd == BPF_MAP_LOOKUP_BATCH ||
4052 cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH) &&
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004053 !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
4054 err = -EPERM;
4055 goto err_put;
4056 }
4057
4058 if (cmd != BPF_MAP_LOOKUP_BATCH &&
4059 !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
4060 err = -EPERM;
4061 goto err_put;
4062 }
4063
4064 if (cmd == BPF_MAP_LOOKUP_BATCH)
4065 BPF_DO_BATCH(map->ops->map_lookup_batch);
Yonghong Song05799632020-01-15 10:43:04 -08004066 else if (cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH)
4067 BPF_DO_BATCH(map->ops->map_lookup_and_delete_batch);
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004068 else if (cmd == BPF_MAP_UPDATE_BATCH)
4069 BPF_DO_BATCH(map->ops->map_update_batch);
4070 else
4071 BPF_DO_BATCH(map->ops->map_delete_batch);
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004072
4073err_put:
4074 fdput(f);
4075 return err;
4076}
4077
Yonghong Songde4e05c2020-05-09 10:59:01 -07004078static int tracing_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
4079{
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004080 if (attr->link_create.attach_type != prog->expected_attach_type)
4081 return -EINVAL;
Yonghong Songde4e05c2020-05-09 10:59:01 -07004082
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004083 if (prog->expected_attach_type == BPF_TRACE_ITER)
4084 return bpf_iter_link_attach(attr, prog);
4085 else if (prog->type == BPF_PROG_TYPE_EXT)
4086 return bpf_tracing_prog_attach(prog,
4087 attr->link_create.target_fd,
4088 attr->link_create.target_btf_id);
Yonghong Songde4e05c2020-05-09 10:59:01 -07004089 return -EINVAL;
4090}
4091
Yonghong Song5e7b3022020-08-04 22:50:56 -07004092#define BPF_LINK_CREATE_LAST_FIELD link_create.iter_info_len
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004093static int link_create(union bpf_attr *attr)
4094{
4095 enum bpf_prog_type ptype;
4096 struct bpf_prog *prog;
4097 int ret;
4098
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004099 if (CHECK_ATTR(BPF_LINK_CREATE))
4100 return -EINVAL;
4101
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004102 prog = bpf_prog_get(attr->link_create.prog_fd);
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004103 if (IS_ERR(prog))
4104 return PTR_ERR(prog);
4105
4106 ret = bpf_prog_attach_check_attach_type(prog,
4107 attr->link_create.attach_type);
4108 if (ret)
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004109 goto out;
4110
4111 if (prog->type == BPF_PROG_TYPE_EXT) {
4112 ret = tracing_bpf_link_attach(attr, prog);
4113 goto out;
4114 }
4115
4116 ptype = attach_type_to_prog_type(attr->link_create.attach_type);
4117 if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type) {
4118 ret = -EINVAL;
4119 goto out;
4120 }
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004121
4122 switch (ptype) {
4123 case BPF_PROG_TYPE_CGROUP_SKB:
4124 case BPF_PROG_TYPE_CGROUP_SOCK:
4125 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
4126 case BPF_PROG_TYPE_SOCK_OPS:
4127 case BPF_PROG_TYPE_CGROUP_DEVICE:
4128 case BPF_PROG_TYPE_CGROUP_SYSCTL:
4129 case BPF_PROG_TYPE_CGROUP_SOCKOPT:
4130 ret = cgroup_bpf_link_attach(attr, prog);
4131 break;
Yonghong Songde4e05c2020-05-09 10:59:01 -07004132 case BPF_PROG_TYPE_TRACING:
4133 ret = tracing_bpf_link_attach(attr, prog);
4134 break;
Jakub Sitnicki7f045a42020-05-31 10:28:38 +02004135 case BPF_PROG_TYPE_FLOW_DISSECTOR:
Jakub Sitnickie9ddbb72020-07-17 12:35:23 +02004136 case BPF_PROG_TYPE_SK_LOOKUP:
Jakub Sitnicki7f045a42020-05-31 10:28:38 +02004137 ret = netns_bpf_link_create(attr, prog);
4138 break;
Andrii Nakryiko310ad792020-07-28 12:05:27 -07004139#ifdef CONFIG_NET
Andrii Nakryikoaa8d3a72020-07-21 23:45:57 -07004140 case BPF_PROG_TYPE_XDP:
4141 ret = bpf_xdp_link_attach(attr, prog);
4142 break;
Andrii Nakryiko310ad792020-07-28 12:05:27 -07004143#endif
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004144 default:
4145 ret = -EINVAL;
4146 }
4147
Toke Høiland-Jørgensen4a1e7c02020-09-29 14:45:51 +02004148out:
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004149 if (ret < 0)
4150 bpf_prog_put(prog);
4151 return ret;
4152}
4153
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004154#define BPF_LINK_UPDATE_LAST_FIELD link_update.old_prog_fd
4155
4156static int link_update(union bpf_attr *attr)
4157{
4158 struct bpf_prog *old_prog = NULL, *new_prog;
4159 struct bpf_link *link;
4160 u32 flags;
4161 int ret;
4162
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004163 if (CHECK_ATTR(BPF_LINK_UPDATE))
4164 return -EINVAL;
4165
4166 flags = attr->link_update.flags;
4167 if (flags & ~BPF_F_REPLACE)
4168 return -EINVAL;
4169
4170 link = bpf_link_get_from_fd(attr->link_update.link_fd);
4171 if (IS_ERR(link))
4172 return PTR_ERR(link);
4173
4174 new_prog = bpf_prog_get(attr->link_update.new_prog_fd);
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07004175 if (IS_ERR(new_prog)) {
4176 ret = PTR_ERR(new_prog);
4177 goto out_put_link;
4178 }
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004179
4180 if (flags & BPF_F_REPLACE) {
4181 old_prog = bpf_prog_get(attr->link_update.old_prog_fd);
4182 if (IS_ERR(old_prog)) {
4183 ret = PTR_ERR(old_prog);
4184 old_prog = NULL;
4185 goto out_put_progs;
4186 }
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07004187 } else if (attr->link_update.old_prog_fd) {
4188 ret = -EINVAL;
4189 goto out_put_progs;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004190 }
4191
Andrii Nakryikof9d04122020-04-28 17:16:05 -07004192 if (link->ops->update_prog)
4193 ret = link->ops->update_prog(link, new_prog, old_prog);
4194 else
Jakub Sitnickife537392020-05-25 14:29:28 +02004195 ret = -EINVAL;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004196
4197out_put_progs:
4198 if (old_prog)
4199 bpf_prog_put(old_prog);
4200 if (ret)
4201 bpf_prog_put(new_prog);
Andrii Nakryiko4adb7a42020-04-23 22:20:44 -07004202out_put_link:
4203 bpf_link_put(link);
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004204 return ret;
4205}
4206
Andrii Nakryiko73b11c2a2020-07-31 11:28:26 -07004207#define BPF_LINK_DETACH_LAST_FIELD link_detach.link_fd
4208
4209static int link_detach(union bpf_attr *attr)
4210{
4211 struct bpf_link *link;
4212 int ret;
4213
4214 if (CHECK_ATTR(BPF_LINK_DETACH))
4215 return -EINVAL;
4216
4217 link = bpf_link_get_from_fd(attr->link_detach.link_fd);
4218 if (IS_ERR(link))
4219 return PTR_ERR(link);
4220
4221 if (link->ops->detach)
4222 ret = link->ops->detach(link);
4223 else
4224 ret = -EOPNOTSUPP;
4225
4226 bpf_link_put(link);
4227 return ret;
4228}
4229
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004230static struct bpf_link *bpf_link_inc_not_zero(struct bpf_link *link)
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004231{
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004232 return atomic64_fetch_add_unless(&link->refcnt, 1, 0) ? link : ERR_PTR(-ENOENT);
4233}
4234
4235struct bpf_link *bpf_link_by_id(u32 id)
4236{
4237 struct bpf_link *link;
4238
4239 if (!id)
4240 return ERR_PTR(-ENOENT);
4241
4242 spin_lock_bh(&link_idr_lock);
4243 /* before link is "settled", ID is 0, pretend it doesn't exist yet */
4244 link = idr_find(&link_idr, id);
4245 if (link) {
4246 if (link->id)
4247 link = bpf_link_inc_not_zero(link);
4248 else
4249 link = ERR_PTR(-EAGAIN);
4250 } else {
4251 link = ERR_PTR(-ENOENT);
4252 }
4253 spin_unlock_bh(&link_idr_lock);
4254 return link;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004255}
4256
4257#define BPF_LINK_GET_FD_BY_ID_LAST_FIELD link_id
4258
4259static int bpf_link_get_fd_by_id(const union bpf_attr *attr)
4260{
4261 struct bpf_link *link;
4262 u32 id = attr->link_id;
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004263 int fd;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004264
4265 if (CHECK_ATTR(BPF_LINK_GET_FD_BY_ID))
4266 return -EINVAL;
4267
4268 if (!capable(CAP_SYS_ADMIN))
4269 return -EPERM;
4270
Alexei Starovoitov005142b2020-08-18 21:27:56 -07004271 link = bpf_link_by_id(id);
4272 if (IS_ERR(link))
4273 return PTR_ERR(link);
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004274
4275 fd = bpf_link_new_fd(link);
4276 if (fd < 0)
4277 bpf_link_put(link);
4278
4279 return fd;
4280}
4281
Song Liud46edd62020-04-30 00:15:04 -07004282DEFINE_MUTEX(bpf_stats_enabled_mutex);
4283
4284static int bpf_stats_release(struct inode *inode, struct file *file)
4285{
4286 mutex_lock(&bpf_stats_enabled_mutex);
4287 static_key_slow_dec(&bpf_stats_enabled_key.key);
4288 mutex_unlock(&bpf_stats_enabled_mutex);
4289 return 0;
4290}
4291
4292static const struct file_operations bpf_stats_fops = {
4293 .release = bpf_stats_release,
4294};
4295
4296static int bpf_enable_runtime_stats(void)
4297{
4298 int fd;
4299
4300 mutex_lock(&bpf_stats_enabled_mutex);
4301
4302 /* Set a very high limit to avoid overflow */
4303 if (static_key_count(&bpf_stats_enabled_key.key) > INT_MAX / 2) {
4304 mutex_unlock(&bpf_stats_enabled_mutex);
4305 return -EBUSY;
4306 }
4307
4308 fd = anon_inode_getfd("bpf-stats", &bpf_stats_fops, NULL, O_CLOEXEC);
4309 if (fd >= 0)
4310 static_key_slow_inc(&bpf_stats_enabled_key.key);
4311
4312 mutex_unlock(&bpf_stats_enabled_mutex);
4313 return fd;
4314}
4315
4316#define BPF_ENABLE_STATS_LAST_FIELD enable_stats.type
4317
4318static int bpf_enable_stats(union bpf_attr *attr)
4319{
4320
4321 if (CHECK_ATTR(BPF_ENABLE_STATS))
4322 return -EINVAL;
4323
4324 if (!capable(CAP_SYS_ADMIN))
4325 return -EPERM;
4326
4327 switch (attr->enable_stats.type) {
4328 case BPF_STATS_RUN_TIME:
4329 return bpf_enable_runtime_stats();
4330 default:
4331 break;
4332 }
4333 return -EINVAL;
4334}
4335
Yonghong Songac51d992020-05-09 10:59:05 -07004336#define BPF_ITER_CREATE_LAST_FIELD iter_create.flags
4337
4338static int bpf_iter_create(union bpf_attr *attr)
4339{
4340 struct bpf_link *link;
4341 int err;
4342
4343 if (CHECK_ATTR(BPF_ITER_CREATE))
4344 return -EINVAL;
4345
4346 if (attr->iter_create.flags)
4347 return -EINVAL;
4348
4349 link = bpf_link_get_from_fd(attr->iter_create.link_fd);
4350 if (IS_ERR(link))
4351 return PTR_ERR(link);
4352
4353 err = bpf_iter_new_fd(link);
4354 bpf_link_put(link);
4355
4356 return err;
4357}
4358
YiFei Zhuef153142020-09-15 16:45:40 -07004359#define BPF_PROG_BIND_MAP_LAST_FIELD prog_bind_map.flags
4360
4361static int bpf_prog_bind_map(union bpf_attr *attr)
4362{
4363 struct bpf_prog *prog;
4364 struct bpf_map *map;
4365 struct bpf_map **used_maps_old, **used_maps_new;
4366 int i, ret = 0;
4367
4368 if (CHECK_ATTR(BPF_PROG_BIND_MAP))
4369 return -EINVAL;
4370
4371 if (attr->prog_bind_map.flags)
4372 return -EINVAL;
4373
4374 prog = bpf_prog_get(attr->prog_bind_map.prog_fd);
4375 if (IS_ERR(prog))
4376 return PTR_ERR(prog);
4377
4378 map = bpf_map_get(attr->prog_bind_map.map_fd);
4379 if (IS_ERR(map)) {
4380 ret = PTR_ERR(map);
4381 goto out_prog_put;
4382 }
4383
4384 mutex_lock(&prog->aux->used_maps_mutex);
4385
4386 used_maps_old = prog->aux->used_maps;
4387
4388 for (i = 0; i < prog->aux->used_map_cnt; i++)
Stanislav Fomichev1028ae42020-10-02 17:25:44 -07004389 if (used_maps_old[i] == map) {
4390 bpf_map_put(map);
YiFei Zhuef153142020-09-15 16:45:40 -07004391 goto out_unlock;
Stanislav Fomichev1028ae42020-10-02 17:25:44 -07004392 }
YiFei Zhuef153142020-09-15 16:45:40 -07004393
4394 used_maps_new = kmalloc_array(prog->aux->used_map_cnt + 1,
4395 sizeof(used_maps_new[0]),
4396 GFP_KERNEL);
4397 if (!used_maps_new) {
4398 ret = -ENOMEM;
4399 goto out_unlock;
4400 }
4401
4402 memcpy(used_maps_new, used_maps_old,
4403 sizeof(used_maps_old[0]) * prog->aux->used_map_cnt);
4404 used_maps_new[prog->aux->used_map_cnt] = map;
4405
4406 prog->aux->used_map_cnt++;
4407 prog->aux->used_maps = used_maps_new;
4408
4409 kfree(used_maps_old);
4410
4411out_unlock:
4412 mutex_unlock(&prog->aux->used_maps_mutex);
4413
4414 if (ret)
4415 bpf_map_put(map);
4416out_prog_put:
4417 bpf_prog_put(prog);
4418 return ret;
4419}
4420
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004421SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
4422{
Greg Kroah-Hartman8096f222020-03-20 10:48:13 +01004423 union bpf_attr attr;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004424 int err;
4425
Alexei Starovoitov2c78ee82020-05-13 16:03:54 -07004426 if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004427 return -EPERM;
4428
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07004429 err = bpf_check_uarg_tail_zero(uattr, sizeof(attr), size);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004430 if (err)
4431 return err;
4432 size = min_t(u32, size, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004433
4434 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
Greg Kroah-Hartman8096f222020-03-20 10:48:13 +01004435 memset(&attr, 0, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004436 if (copy_from_user(&attr, uattr, size) != 0)
4437 return -EFAULT;
4438
Chenbo Fengafdb09c2017-10-18 13:00:24 -07004439 err = security_bpf(cmd, &attr, size);
4440 if (err < 0)
4441 return err;
4442
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004443 switch (cmd) {
4444 case BPF_MAP_CREATE:
4445 err = map_create(&attr);
4446 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07004447 case BPF_MAP_LOOKUP_ELEM:
4448 err = map_lookup_elem(&attr);
4449 break;
4450 case BPF_MAP_UPDATE_ELEM:
4451 err = map_update_elem(&attr);
4452 break;
4453 case BPF_MAP_DELETE_ELEM:
4454 err = map_delete_elem(&attr);
4455 break;
4456 case BPF_MAP_GET_NEXT_KEY:
4457 err = map_get_next_key(&attr);
4458 break;
Daniel Borkmann87df15d2019-04-09 23:20:06 +02004459 case BPF_MAP_FREEZE:
4460 err = map_freeze(&attr);
4461 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07004462 case BPF_PROG_LOAD:
Yonghong Song838e9692018-11-19 15:29:11 -08004463 err = bpf_prog_load(&attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07004464 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01004465 case BPF_OBJ_PIN:
4466 err = bpf_obj_pin(&attr);
4467 break;
4468 case BPF_OBJ_GET:
4469 err = bpf_obj_get(&attr);
4470 break;
Daniel Mackf4324552016-11-23 16:52:27 +01004471 case BPF_PROG_ATTACH:
4472 err = bpf_prog_attach(&attr);
4473 break;
4474 case BPF_PROG_DETACH:
4475 err = bpf_prog_detach(&attr);
4476 break;
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07004477 case BPF_PROG_QUERY:
4478 err = bpf_prog_query(&attr, uattr);
4479 break;
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07004480 case BPF_PROG_TEST_RUN:
4481 err = bpf_prog_test_run(&attr, uattr);
4482 break;
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07004483 case BPF_PROG_GET_NEXT_ID:
4484 err = bpf_obj_get_next_id(&attr, uattr,
4485 &prog_idr, &prog_idr_lock);
4486 break;
4487 case BPF_MAP_GET_NEXT_ID:
4488 err = bpf_obj_get_next_id(&attr, uattr,
4489 &map_idr, &map_idr_lock);
4490 break;
Quentin Monnet1b9ed842019-08-20 10:31:50 +01004491 case BPF_BTF_GET_NEXT_ID:
4492 err = bpf_obj_get_next_id(&attr, uattr,
4493 &btf_idr, &btf_idr_lock);
4494 break;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07004495 case BPF_PROG_GET_FD_BY_ID:
4496 err = bpf_prog_get_fd_by_id(&attr);
4497 break;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07004498 case BPF_MAP_GET_FD_BY_ID:
4499 err = bpf_map_get_fd_by_id(&attr);
4500 break;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07004501 case BPF_OBJ_GET_INFO_BY_FD:
4502 err = bpf_obj_get_info_by_fd(&attr, uattr);
4503 break;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07004504 case BPF_RAW_TRACEPOINT_OPEN:
4505 err = bpf_raw_tracepoint_open(&attr);
4506 break;
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07004507 case BPF_BTF_LOAD:
4508 err = bpf_btf_load(&attr);
4509 break;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07004510 case BPF_BTF_GET_FD_BY_ID:
4511 err = bpf_btf_get_fd_by_id(&attr);
4512 break;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07004513 case BPF_TASK_FD_QUERY:
4514 err = bpf_task_fd_query(&attr, uattr);
4515 break;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02004516 case BPF_MAP_LOOKUP_AND_DELETE_ELEM:
4517 err = map_lookup_and_delete_elem(&attr);
4518 break;
Brian Vazquezcb4d03a2020-01-15 10:43:01 -08004519 case BPF_MAP_LOOKUP_BATCH:
4520 err = bpf_map_do_batch(&attr, uattr, BPF_MAP_LOOKUP_BATCH);
4521 break;
Yonghong Song05799632020-01-15 10:43:04 -08004522 case BPF_MAP_LOOKUP_AND_DELETE_BATCH:
4523 err = bpf_map_do_batch(&attr, uattr,
4524 BPF_MAP_LOOKUP_AND_DELETE_BATCH);
4525 break;
Brian Vazquezaa2e93b2020-01-15 10:43:02 -08004526 case BPF_MAP_UPDATE_BATCH:
4527 err = bpf_map_do_batch(&attr, uattr, BPF_MAP_UPDATE_BATCH);
4528 break;
4529 case BPF_MAP_DELETE_BATCH:
4530 err = bpf_map_do_batch(&attr, uattr, BPF_MAP_DELETE_BATCH);
4531 break;
Andrii Nakryikoaf6eea52020-03-29 19:59:58 -07004532 case BPF_LINK_CREATE:
4533 err = link_create(&attr);
4534 break;
Andrii Nakryiko0c991eb2020-03-29 19:59:59 -07004535 case BPF_LINK_UPDATE:
4536 err = link_update(&attr);
4537 break;
Andrii Nakryiko2d602c82020-04-28 17:16:07 -07004538 case BPF_LINK_GET_FD_BY_ID:
4539 err = bpf_link_get_fd_by_id(&attr);
4540 break;
4541 case BPF_LINK_GET_NEXT_ID:
4542 err = bpf_obj_get_next_id(&attr, uattr,
4543 &link_idr, &link_idr_lock);
4544 break;
Song Liud46edd62020-04-30 00:15:04 -07004545 case BPF_ENABLE_STATS:
4546 err = bpf_enable_stats(&attr);
4547 break;
Yonghong Songac51d992020-05-09 10:59:05 -07004548 case BPF_ITER_CREATE:
4549 err = bpf_iter_create(&attr);
4550 break;
Andrii Nakryiko73b11c2a2020-07-31 11:28:26 -07004551 case BPF_LINK_DETACH:
4552 err = link_detach(&attr);
4553 break;
YiFei Zhuef153142020-09-15 16:45:40 -07004554 case BPF_PROG_BIND_MAP:
4555 err = bpf_prog_bind_map(&attr);
4556 break;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07004557 default:
4558 err = -EINVAL;
4559 break;
4560 }
4561
4562 return err;
4563}