blob: 56b4b0e08b3bae986a795b3a98d21c25799c5071 [file] [log] [blame]
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07001/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
11 */
12#include <linux/bpf.h>
Daniel Borkmanna67edbf2017-01-25 02:28:18 +010013#include <linux/bpf_trace.h>
Sean Youngf4364dc2018-05-27 12:24:09 +010014#include <linux/bpf_lirc.h>
Martin KaFai Lauf56a6532018-04-18 15:56:01 -070015#include <linux/btf.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070016#include <linux/syscalls.h>
17#include <linux/slab.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010018#include <linux/sched/signal.h>
Daniel Borkmannd407bd22017-01-18 15:14:17 +010019#include <linux/vmalloc.h>
20#include <linux/mmzone.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070021#include <linux/anon_inodes.h>
Yonghong Song41bdc4b2018-05-24 11:21:09 -070022#include <linux/fdtable.h>
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -070023#include <linux/file.h>
Yonghong Song41bdc4b2018-05-24 11:21:09 -070024#include <linux/fs.h>
Alexei Starovoitov09756af2014-09-26 00:17:00 -070025#include <linux/license.h>
26#include <linux/filter.h>
Alexei Starovoitov25415172015-03-25 12:49:20 -070027#include <linux/version.h>
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +010028#include <linux/kernel.h>
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070029#include <linux/idr.h>
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -070030#include <linux/cred.h>
31#include <linux/timekeeping.h>
32#include <linux/ctype.h>
Mark Rutland9ef09e32018-05-03 17:04:59 +010033#include <linux/nospec.h>
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070034
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -070035#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \
36 (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_HASH(map) ((map)->map_type == BPF_MAP_TYPE_HASH_OF_MAPS)
40#define IS_FD_MAP(map) (IS_FD_ARRAY(map) || IS_FD_HASH(map))
41
Chenbo Feng6e71b042017-10-18 13:00:22 -070042#define BPF_OBJ_FLAG_MASK (BPF_F_RDONLY | BPF_F_WRONLY)
43
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080044DEFINE_PER_CPU(int, bpf_prog_active);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -070045static DEFINE_IDR(prog_idr);
46static DEFINE_SPINLOCK(prog_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -070047static DEFINE_IDR(map_idr);
48static DEFINE_SPINLOCK(map_idr_lock);
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -080049
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070050int sysctl_unprivileged_bpf_disabled __read_mostly;
51
Johannes Berg40077e02017-04-11 15:34:58 +020052static const struct bpf_map_ops * const bpf_map_types[] = {
53#define BPF_PROG_TYPE(_id, _ops)
54#define BPF_MAP_TYPE(_id, _ops) \
55 [_id] = &_ops,
56#include <linux/bpf_types.h>
57#undef BPF_PROG_TYPE
58#undef BPF_MAP_TYPE
59};
Alexei Starovoitov99c55f72014-09-26 00:16:57 -070060
Mickaël Salaün752ba562017-08-07 20:45:20 +020061/*
62 * If we're handed a bigger struct than we know of, ensure all the unknown bits
63 * are 0 - i.e. new user-space does not rely on any kernel feature extensions
64 * we don't know about yet.
65 *
66 * There is a ToCToU between this function call and the following
67 * copy_from_user() call. However, this is not a concern since this function is
68 * meant to be a future-proofing of bits.
69 */
Martin KaFai Laudcab51f2018-05-22 15:03:31 -070070int bpf_check_uarg_tail_zero(void __user *uaddr,
71 size_t expected_size,
72 size_t actual_size)
Mickaël Salaün58291a72017-08-07 20:45:19 +020073{
74 unsigned char __user *addr;
75 unsigned char __user *end;
76 unsigned char val;
77 int err;
78
Mickaël Salaün752ba562017-08-07 20:45:20 +020079 if (unlikely(actual_size > PAGE_SIZE)) /* silly large */
80 return -E2BIG;
81
Linus Torvalds96d4f262019-01-03 18:57:57 -080082 if (unlikely(!access_ok(uaddr, actual_size)))
Mickaël Salaün752ba562017-08-07 20:45:20 +020083 return -EFAULT;
84
Mickaël Salaün58291a72017-08-07 20:45:19 +020085 if (actual_size <= expected_size)
86 return 0;
87
88 addr = uaddr + expected_size;
89 end = uaddr + actual_size;
90
91 for (; addr < end; addr++) {
92 err = get_user(val, addr);
93 if (err)
94 return err;
95 if (val)
96 return -E2BIG;
97 }
98
99 return 0;
100}
101
Jakub Kicinskia3884572018-01-11 20:29:09 -0800102const struct bpf_map_ops bpf_map_offload_ops = {
103 .map_alloc = bpf_map_offload_map_alloc,
104 .map_free = bpf_map_offload_map_free,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200105 .map_check_btf = map_check_no_btf,
Jakub Kicinskia3884572018-01-11 20:29:09 -0800106};
107
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700108static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
109{
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800110 const struct bpf_map_ops *ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100111 u32 type = attr->map_type;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700112 struct bpf_map *map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800113 int err;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700114
Mark Rutland9ef09e32018-05-03 17:04:59 +0100115 if (type >= ARRAY_SIZE(bpf_map_types))
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800116 return ERR_PTR(-EINVAL);
Mark Rutland9ef09e32018-05-03 17:04:59 +0100117 type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types));
118 ops = bpf_map_types[type];
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800119 if (!ops)
Johannes Berg40077e02017-04-11 15:34:58 +0200120 return ERR_PTR(-EINVAL);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700121
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800122 if (ops->map_alloc_check) {
123 err = ops->map_alloc_check(attr);
124 if (err)
125 return ERR_PTR(err);
126 }
Jakub Kicinskia3884572018-01-11 20:29:09 -0800127 if (attr->map_ifindex)
128 ops = &bpf_map_offload_ops;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800129 map = ops->map_alloc(attr);
Johannes Berg40077e02017-04-11 15:34:58 +0200130 if (IS_ERR(map))
131 return map;
Jakub Kicinski1110f3a2018-01-11 20:29:03 -0800132 map->ops = ops;
Mark Rutland9ef09e32018-05-03 17:04:59 +0100133 map->map_type = type;
Johannes Berg40077e02017-04-11 15:34:58 +0200134 return map;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700135}
136
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700137void *bpf_map_area_alloc(size_t size, int numa_node)
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100138{
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100139 /* We really just want to fail instead of triggering OOM killer
140 * under memory pressure, therefore we set __GFP_NORETRY to kmalloc,
141 * which is used for lower order allocation requests.
142 *
143 * It has been observed that higher order allocation requests done by
144 * vmalloc with __GFP_NORETRY being set might fail due to not trying
145 * to reclaim memory from the page cache, thus we set
146 * __GFP_RETRY_MAYFAIL to avoid such situations.
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100147 */
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100148
149 const gfp_t flags = __GFP_NOWARN | __GFP_ZERO;
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100150 void *area;
151
152 if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100153 area = kmalloc_node(size, GFP_USER | __GFP_NORETRY | flags,
154 numa_node);
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100155 if (area != NULL)
156 return area;
157 }
158
Martynas Pumputisf01a7db2019-03-18 16:10:26 +0100159 return __vmalloc_node_flags_caller(size, numa_node,
160 GFP_KERNEL | __GFP_RETRY_MAYFAIL |
161 flags, __builtin_return_address(0));
Daniel Borkmannd407bd22017-01-18 15:14:17 +0100162}
163
164void bpf_map_area_free(void *area)
165{
166 kvfree(area);
167}
168
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200169static u32 bpf_map_flags_retain_permanent(u32 flags)
170{
171 /* Some map creation flags are not tied to the map object but
172 * rather to the map fd instead, so they have no meaning upon
173 * map object inspection since multiple file descriptors with
174 * different (access) properties can exist here. Thus, given
175 * this has zero meaning for the map itself, lets clear these
176 * from here.
177 */
178 return flags & ~(BPF_F_RDONLY | BPF_F_WRONLY);
179}
180
Jakub Kicinskibd475642018-01-11 20:29:06 -0800181void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr)
182{
183 map->map_type = attr->map_type;
184 map->key_size = attr->key_size;
185 map->value_size = attr->value_size;
186 map->max_entries = attr->max_entries;
Daniel Borkmannbe70bcd2019-04-09 23:20:04 +0200187 map->map_flags = bpf_map_flags_retain_permanent(attr->map_flags);
Jakub Kicinskibd475642018-01-11 20:29:06 -0800188 map->numa_node = bpf_map_attr_numa_node(attr);
189}
190
Alexei Starovoitov6c905982016-03-07 21:57:15 -0800191int bpf_map_precharge_memlock(u32 pages)
192{
193 struct user_struct *user = get_current_user();
194 unsigned long memlock_limit, cur;
195
196 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
197 cur = atomic_long_read(&user->locked_vm);
198 free_uid(user);
199 if (cur + pages > memlock_limit)
200 return -EPERM;
201 return 0;
202}
203
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700204static int bpf_charge_memlock(struct user_struct *user, u32 pages)
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700205{
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700206 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700207
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700208 if (atomic_long_add_return(pages, &user->locked_vm) > memlock_limit) {
209 atomic_long_sub(pages, &user->locked_vm);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700210 return -EPERM;
211 }
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700212 return 0;
213}
214
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700215static void bpf_uncharge_memlock(struct user_struct *user, u32 pages)
216{
217 atomic_long_sub(pages, &user->locked_vm);
218}
219
220static int bpf_map_init_memlock(struct bpf_map *map)
221{
222 struct user_struct *user = get_current_user();
223 int ret;
224
225 ret = bpf_charge_memlock(user, map->pages);
226 if (ret) {
227 free_uid(user);
228 return ret;
229 }
230 map->user = user;
231 return ret;
232}
233
234static void bpf_map_release_memlock(struct bpf_map *map)
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700235{
236 struct user_struct *user = map->user;
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700237 bpf_uncharge_memlock(user, map->pages);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700238 free_uid(user);
239}
240
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700241int bpf_map_charge_memlock(struct bpf_map *map, u32 pages)
242{
243 int ret;
244
245 ret = bpf_charge_memlock(map->user, pages);
246 if (ret)
247 return ret;
248 map->pages += pages;
249 return ret;
250}
251
252void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages)
253{
254 bpf_uncharge_memlock(map->user, pages);
255 map->pages -= pages;
256}
257
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700258static int bpf_map_alloc_id(struct bpf_map *map)
259{
260 int id;
261
Shaohua Lib76354c2018-03-27 11:53:21 -0700262 idr_preload(GFP_KERNEL);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700263 spin_lock_bh(&map_idr_lock);
264 id = idr_alloc_cyclic(&map_idr, map, 1, INT_MAX, GFP_ATOMIC);
265 if (id > 0)
266 map->id = id;
267 spin_unlock_bh(&map_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -0700268 idr_preload_end();
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700269
270 if (WARN_ON_ONCE(!id))
271 return -ENOSPC;
272
273 return id > 0 ? 0 : id;
274}
275
Jakub Kicinskia3884572018-01-11 20:29:09 -0800276void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700277{
Eric Dumazet930651a2017-09-19 09:15:59 -0700278 unsigned long flags;
279
Jakub Kicinskia3884572018-01-11 20:29:09 -0800280 /* Offloaded maps are removed from the IDR store when their device
281 * disappears - even if someone holds an fd to them they are unusable,
282 * the memory is gone, all ops will fail; they are simply waiting for
283 * refcnt to drop to be freed.
284 */
285 if (!map->id)
286 return;
287
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700288 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700289 spin_lock_irqsave(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700290 else
291 __acquire(&map_idr_lock);
292
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700293 idr_remove(&map_idr, map->id);
Jakub Kicinskia3884572018-01-11 20:29:09 -0800294 map->id = 0;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700295
296 if (do_idr_lock)
Eric Dumazet930651a2017-09-19 09:15:59 -0700297 spin_unlock_irqrestore(&map_idr_lock, flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700298 else
299 __release(&map_idr_lock);
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700300}
301
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700302/* called from workqueue */
303static void bpf_map_free_deferred(struct work_struct *work)
304{
305 struct bpf_map *map = container_of(work, struct bpf_map, work);
306
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700307 bpf_map_release_memlock(map);
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700308 security_bpf_map_free(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700309 /* implementation dependent freeing */
310 map->ops->map_free(map);
311}
312
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100313static void bpf_map_put_uref(struct bpf_map *map)
314{
315 if (atomic_dec_and_test(&map->usercnt)) {
John Fastabendba6b8de2018-04-23 15:39:23 -0700316 if (map->ops->map_release_uref)
317 map->ops->map_release_uref(map);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100318 }
319}
320
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700321/* decrement map refcnt and schedule it for freeing via workqueue
322 * (unrelying map implementation ops->map_free() might sleep)
323 */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700324static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock)
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700325{
326 if (atomic_dec_and_test(&map->refcnt)) {
Martin KaFai Lau34ad5582017-06-05 12:15:48 -0700327 /* bpf_map_free_id() must be called first */
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700328 bpf_map_free_id(map, do_idr_lock);
Martin KaFai Lau78958fc2018-05-04 14:49:51 -0700329 btf_put(map->btf);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700330 INIT_WORK(&map->work, bpf_map_free_deferred);
331 schedule_work(&map->work);
332 }
333}
334
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700335void bpf_map_put(struct bpf_map *map)
336{
337 __bpf_map_put(map, true);
338}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700339EXPORT_SYMBOL_GPL(bpf_map_put);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700340
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100341void bpf_map_put_with_uref(struct bpf_map *map)
342{
343 bpf_map_put_uref(map);
344 bpf_map_put(map);
345}
346
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700347static int bpf_map_release(struct inode *inode, struct file *filp)
348{
Daniel Borkmann61d1b6a2016-06-15 22:47:12 +0200349 struct bpf_map *map = filp->private_data;
350
351 if (map->ops->map_release)
352 map->ops->map_release(map, filp);
353
354 bpf_map_put_with_uref(map);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700355 return 0;
356}
357
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100358#ifdef CONFIG_PROC_FS
359static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
360{
361 const struct bpf_map *map = filp->private_data;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100362 const struct bpf_array *array;
363 u32 owner_prog_type = 0;
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200364 u32 owner_jited = 0;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100365
366 if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) {
367 array = container_of(map, struct bpf_array, map);
368 owner_prog_type = array->owner_prog_type;
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200369 owner_jited = array->owner_jited;
Daniel Borkmann21116b72016-11-26 01:28:07 +0100370 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100371
372 seq_printf(m,
373 "map_type:\t%u\n"
374 "key_size:\t%u\n"
375 "value_size:\t%u\n"
Daniel Borkmann322cea22016-03-25 00:30:25 +0100376 "max_entries:\t%u\n"
Daniel Borkmann21116b72016-11-26 01:28:07 +0100377 "map_flags:\t%#x\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +0200378 "memlock:\t%llu\n"
379 "map_id:\t%u\n",
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100380 map->map_type,
381 map->key_size,
382 map->value_size,
Daniel Borkmann322cea22016-03-25 00:30:25 +0100383 map->max_entries,
Daniel Borkmann21116b72016-11-26 01:28:07 +0100384 map->map_flags,
Daniel Borkmann4316b402018-06-02 23:06:34 +0200385 map->pages * 1ULL << PAGE_SHIFT,
386 map->id);
Daniel Borkmann21116b72016-11-26 01:28:07 +0100387
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200388 if (owner_prog_type) {
Daniel Borkmann21116b72016-11-26 01:28:07 +0100389 seq_printf(m, "owner_prog_type:\t%u\n",
390 owner_prog_type);
Daniel Borkmann9780c0a2017-07-02 02:13:28 +0200391 seq_printf(m, "owner_jited:\t%u\n",
392 owner_jited);
393 }
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100394}
395#endif
396
Chenbo Feng6e71b042017-10-18 13:00:22 -0700397static ssize_t bpf_dummy_read(struct file *filp, char __user *buf, size_t siz,
398 loff_t *ppos)
399{
400 /* We need this handler such that alloc_file() enables
401 * f_mode with FMODE_CAN_READ.
402 */
403 return -EINVAL;
404}
405
406static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
407 size_t siz, loff_t *ppos)
408{
409 /* We need this handler such that alloc_file() enables
410 * f_mode with FMODE_CAN_WRITE.
411 */
412 return -EINVAL;
413}
414
Chenbo Fengf66e4482017-10-18 13:00:26 -0700415const struct file_operations bpf_map_fops = {
Daniel Borkmannf99bf202015-11-19 11:56:22 +0100416#ifdef CONFIG_PROC_FS
417 .show_fdinfo = bpf_map_show_fdinfo,
418#endif
419 .release = bpf_map_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700420 .read = bpf_dummy_read,
421 .write = bpf_dummy_write,
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700422};
423
Chenbo Feng6e71b042017-10-18 13:00:22 -0700424int bpf_map_new_fd(struct bpf_map *map, int flags)
Daniel Borkmannaa797812015-10-29 14:58:06 +0100425{
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700426 int ret;
427
428 ret = security_bpf_map(map, OPEN_FMODE(flags));
429 if (ret < 0)
430 return ret;
431
Daniel Borkmannaa797812015-10-29 14:58:06 +0100432 return anon_inode_getfd("bpf-map", &bpf_map_fops, map,
Chenbo Feng6e71b042017-10-18 13:00:22 -0700433 flags | O_CLOEXEC);
434}
435
436int bpf_get_file_flag(int flags)
437{
438 if ((flags & BPF_F_RDONLY) && (flags & BPF_F_WRONLY))
439 return -EINVAL;
440 if (flags & BPF_F_RDONLY)
441 return O_RDONLY;
442 if (flags & BPF_F_WRONLY)
443 return O_WRONLY;
444 return O_RDWR;
Daniel Borkmannaa797812015-10-29 14:58:06 +0100445}
446
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700447/* helper macro to check that unused fields 'union bpf_attr' are zero */
448#define CHECK_ATTR(CMD) \
449 memchr_inv((void *) &attr->CMD##_LAST_FIELD + \
450 sizeof(attr->CMD##_LAST_FIELD), 0, \
451 sizeof(*attr) - \
452 offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
453 sizeof(attr->CMD##_LAST_FIELD)) != NULL
454
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700455/* dst and src must have at least BPF_OBJ_NAME_LEN number of bytes.
456 * Return 0 on success and < 0 on error.
457 */
458static int bpf_obj_name_cpy(char *dst, const char *src)
459{
460 const char *end = src + BPF_OBJ_NAME_LEN;
461
Martin KaFai Lau473d9732017-10-05 21:52:11 -0700462 memset(dst, 0, BPF_OBJ_NAME_LEN);
463
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700464 /* Copy all isalnum() and '_' char */
465 while (src < end && *src) {
466 if (!isalnum(*src) && *src != '_')
467 return -EINVAL;
468 *dst++ = *src++;
469 }
470
471 /* No '\0' found in BPF_OBJ_NAME_LEN number of bytes */
472 if (src == end)
473 return -EINVAL;
474
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -0700475 return 0;
476}
477
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200478int map_check_no_btf(const struct bpf_map *map,
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800479 const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200480 const struct btf_type *key_type,
481 const struct btf_type *value_type)
482{
483 return -ENOTSUPP;
484}
485
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800486static int map_check_btf(struct bpf_map *map, const struct btf *btf,
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200487 u32 btf_key_id, u32 btf_value_id)
488{
489 const struct btf_type *key_type, *value_type;
490 u32 key_size, value_size;
491 int ret = 0;
492
493 key_type = btf_type_id_size(btf, &btf_key_id, &key_size);
494 if (!key_type || key_size != map->key_size)
495 return -EINVAL;
496
497 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
498 if (!value_type || value_size != map->value_size)
499 return -EINVAL;
500
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800501 map->spin_lock_off = btf_find_spin_lock(btf, value_type);
502
503 if (map_value_has_spin_lock(map)) {
504 if (map->map_type != BPF_MAP_TYPE_HASH &&
Alexei Starovoitove16d2f1a2019-01-31 15:40:05 -0800505 map->map_type != BPF_MAP_TYPE_ARRAY &&
506 map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE)
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800507 return -ENOTSUPP;
508 if (map->spin_lock_off + sizeof(struct bpf_spin_lock) >
509 map->value_size) {
510 WARN_ONCE(1,
511 "verifier bug spin_lock_off %d value_size %d\n",
512 map->spin_lock_off, map->value_size);
513 return -EFAULT;
514 }
515 }
516
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200517 if (map->ops->map_check_btf)
Roman Gushchin1b2b2342018-12-10 15:43:00 -0800518 ret = map->ops->map_check_btf(map, btf, key_type, value_type);
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200519
520 return ret;
521}
522
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -0700523#define BPF_MAP_CREATE_LAST_FIELD btf_value_type_id
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700524/* called via syscall */
525static int map_create(union bpf_attr *attr)
526{
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700527 int numa_node = bpf_map_attr_numa_node(attr);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700528 struct bpf_map *map;
Chenbo Feng6e71b042017-10-18 13:00:22 -0700529 int f_flags;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700530 int err;
531
532 err = CHECK_ATTR(BPF_MAP_CREATE);
533 if (err)
534 return -EINVAL;
535
Chenbo Feng6e71b042017-10-18 13:00:22 -0700536 f_flags = bpf_get_file_flag(attr->map_flags);
537 if (f_flags < 0)
538 return f_flags;
539
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700540 if (numa_node != NUMA_NO_NODE &&
Eric Dumazet96e5ae42017-09-04 22:41:02 -0700541 ((unsigned int)numa_node >= nr_node_ids ||
542 !node_online(numa_node)))
Martin KaFai Lau96eabe72017-08-18 11:28:00 -0700543 return -EINVAL;
544
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700545 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
546 map = find_and_alloc_map(attr);
547 if (IS_ERR(map))
548 return PTR_ERR(map);
549
Martin KaFai Lauad5b1772017-09-27 14:37:53 -0700550 err = bpf_obj_name_cpy(map->name, attr->map_name);
551 if (err)
552 goto free_map_nouncharge;
553
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700554 atomic_set(&map->refcnt, 1);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100555 atomic_set(&map->usercnt, 1);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700556
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200557 if (attr->btf_key_type_id || attr->btf_value_type_id) {
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700558 struct btf *btf;
559
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -0700560 if (!attr->btf_key_type_id || !attr->btf_value_type_id) {
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700561 err = -EINVAL;
562 goto free_map_nouncharge;
563 }
564
565 btf = btf_get_by_fd(attr->btf_fd);
566 if (IS_ERR(btf)) {
567 err = PTR_ERR(btf);
568 goto free_map_nouncharge;
569 }
570
Daniel Borkmanne8d2bec2018-08-12 01:59:17 +0200571 err = map_check_btf(map, btf, attr->btf_key_type_id,
572 attr->btf_value_type_id);
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700573 if (err) {
574 btf_put(btf);
575 goto free_map_nouncharge;
576 }
577
578 map->btf = btf;
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -0700579 map->btf_key_type_id = attr->btf_key_type_id;
580 map->btf_value_type_id = attr->btf_value_type_id;
Alexei Starovoitovd83525c2019-01-31 15:40:04 -0800581 } else {
582 map->spin_lock_off = -EINVAL;
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700583 }
584
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700585 err = security_bpf_map_alloc(map);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700586 if (err)
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100587 goto free_map_nouncharge;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -0700588
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700589 err = bpf_map_init_memlock(map);
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700590 if (err)
591 goto free_map_sec;
592
Martin KaFai Lauf3f1c052017-06-05 12:15:47 -0700593 err = bpf_map_alloc_id(map);
594 if (err)
595 goto free_map;
596
Chenbo Feng6e71b042017-10-18 13:00:22 -0700597 err = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700598 if (err < 0) {
599 /* failed to allocate fd.
Peng Sun352d20d2019-02-27 22:36:25 +0800600 * bpf_map_put_with_uref() is needed because the above
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700601 * bpf_map_alloc_id() has published the map
602 * to the userspace and the userspace may
603 * have refcnt-ed it through BPF_MAP_GET_FD_BY_ID.
604 */
Peng Sun352d20d2019-02-27 22:36:25 +0800605 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700606 return err;
607 }
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700608
609 return err;
610
611free_map:
Roman Gushchin0a4c58f2018-08-02 14:27:17 -0700612 bpf_map_release_memlock(map);
Chenbo Fengafdb09c2017-10-18 13:00:24 -0700613free_map_sec:
614 security_bpf_map_free(map);
Daniel Borkmann20b2b242016-11-04 00:56:31 +0100615free_map_nouncharge:
Martin KaFai Laua26ca7c2018-04-18 15:56:03 -0700616 btf_put(map->btf);
Alexei Starovoitov99c55f72014-09-26 00:16:57 -0700617 map->ops->map_free(map);
618 return err;
619}
620
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700621/* if error is returned, fd is released.
622 * On success caller should complete fd access with matching fdput()
623 */
Daniel Borkmannc2101292015-10-29 14:58:07 +0100624struct bpf_map *__bpf_map_get(struct fd f)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700625{
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700626 if (!f.file)
627 return ERR_PTR(-EBADF);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700628 if (f.file->f_op != &bpf_map_fops) {
629 fdput(f);
630 return ERR_PTR(-EINVAL);
631 }
632
Daniel Borkmannc2101292015-10-29 14:58:07 +0100633 return f.file->private_data;
634}
635
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700636/* prog's and map's refcnt limit */
637#define BPF_MAX_REFCNT 32768
638
639struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100640{
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700641 if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
642 atomic_dec(&map->refcnt);
643 return ERR_PTR(-EBUSY);
644 }
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100645 if (uref)
646 atomic_inc(&map->usercnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700647 return map;
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100648}
Jakub Kicinski630a4d32018-05-03 18:37:09 -0700649EXPORT_SYMBOL_GPL(bpf_map_inc);
Daniel Borkmannc9da1612015-11-24 21:28:15 +0100650
651struct bpf_map *bpf_map_get_with_uref(u32 ufd)
Daniel Borkmannc2101292015-10-29 14:58:07 +0100652{
653 struct fd f = fdget(ufd);
654 struct bpf_map *map;
655
656 map = __bpf_map_get(f);
657 if (IS_ERR(map))
658 return map;
659
Alexei Starovoitov92117d82016-04-27 18:56:20 -0700660 map = bpf_map_inc(map, true);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100661 fdput(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700662
663 return map;
664}
665
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700666/* map_idr_lock should have been held */
667static struct bpf_map *bpf_map_inc_not_zero(struct bpf_map *map,
668 bool uref)
669{
670 int refold;
671
Mark Rutlandbfc18e32018-06-21 13:13:04 +0100672 refold = atomic_fetch_add_unless(&map->refcnt, 1, 0);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -0700673
674 if (refold >= BPF_MAX_REFCNT) {
675 __bpf_map_put(map, false);
676 return ERR_PTR(-EBUSY);
677 }
678
679 if (!refold)
680 return ERR_PTR(-ENOENT);
681
682 if (uref)
683 atomic_inc(&map->usercnt);
684
685 return map;
686}
687
Alexei Starovoitovb8cdc052016-03-09 18:56:49 -0800688int __weak bpf_stackmap_copy(struct bpf_map *map, void *key, void *value)
689{
690 return -ENOTSUPP;
691}
692
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +0200693static void *__bpf_copy_key(void __user *ukey, u64 key_size)
694{
695 if (key_size)
696 return memdup_user(ukey, key_size);
697
698 if (ukey)
699 return ERR_PTR(-EINVAL);
700
701 return NULL;
702}
703
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700704/* last field in 'union bpf_attr' used by this command */
Alexei Starovoitov96049f32019-01-31 15:40:09 -0800705#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700706
707static int map_lookup_elem(union bpf_attr *attr)
708{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100709 void __user *ukey = u64_to_user_ptr(attr->key);
710 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700711 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700712 struct bpf_map *map;
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800713 void *key, *value, *ptr;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800714 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200715 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700716 int err;
717
718 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
719 return -EINVAL;
720
Alexei Starovoitov96049f32019-01-31 15:40:09 -0800721 if (attr->flags & ~BPF_F_LOCK)
722 return -EINVAL;
723
Daniel Borkmann592867b2015-09-08 18:00:09 +0200724 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100725 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700726 if (IS_ERR(map))
727 return PTR_ERR(map);
728
Chenbo Feng6e71b042017-10-18 13:00:22 -0700729 if (!(f.file->f_mode & FMODE_CAN_READ)) {
730 err = -EPERM;
731 goto err_put;
732 }
733
Alexei Starovoitov96049f32019-01-31 15:40:09 -0800734 if ((attr->flags & BPF_F_LOCK) &&
735 !map_value_has_spin_lock(map)) {
736 err = -EINVAL;
737 goto err_put;
738 }
739
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +0200740 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -0400741 if (IS_ERR(key)) {
742 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700743 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -0400744 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700745
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800746 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800747 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Roman Gushchinb741f162018-09-28 14:45:43 +0000748 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
749 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800750 value_size = round_up(map->value_size, 8) * num_possible_cpus();
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -0700751 else if (IS_FD_MAP(map))
752 value_size = sizeof(u32);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800753 else
754 value_size = map->value_size;
755
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800756 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800757 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700758 if (!value)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800759 goto free_key;
760
Jakub Kicinskia3884572018-01-11 20:29:09 -0800761 if (bpf_map_is_dev_bound(map)) {
762 err = bpf_map_offload_lookup_elem(map, key, value);
Martin KaFai Lau7c4cd052019-01-30 18:12:45 -0800763 goto done;
764 }
765
766 preempt_disable();
767 this_cpu_inc(bpf_prog_active);
768 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
769 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800770 err = bpf_percpu_hash_copy(map, key, value);
771 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
772 err = bpf_percpu_array_copy(map, key, value);
Roman Gushchinb741f162018-09-28 14:45:43 +0000773 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
774 err = bpf_percpu_cgroup_storage_copy(map, key, value);
Alexei Starovoitov557c0c62016-03-07 21:57:17 -0800775 } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) {
776 err = bpf_stackmap_copy(map, key, value);
Martin KaFai Lau14dc6f02017-06-27 23:08:34 -0700777 } else if (IS_FD_ARRAY(map)) {
778 err = bpf_fd_array_map_lookup_elem(map, key, value);
779 } else if (IS_FD_HASH(map)) {
780 err = bpf_fd_htab_map_lookup_elem(map, key, value);
Martin KaFai Lau5dc4c4b2018-08-08 01:01:24 -0700781 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
782 err = bpf_fd_reuseport_array_lookup_elem(map, key, value);
Mauricio Vasquez Bf1a2e442018-10-18 15:16:25 +0200783 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
784 map->map_type == BPF_MAP_TYPE_STACK) {
785 err = map->ops->map_peek_elem(map, value);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800786 } else {
787 rcu_read_lock();
788 ptr = map->ops->map_lookup_elem(map, key);
Prashant Bhole509db282018-10-09 10:04:49 +0900789 if (IS_ERR(ptr)) {
790 err = PTR_ERR(ptr);
791 } else if (!ptr) {
792 err = -ENOENT;
793 } else {
794 err = 0;
Alexei Starovoitov96049f32019-01-31 15:40:09 -0800795 if (attr->flags & BPF_F_LOCK)
796 /* lock 'ptr' and copy everything but lock */
797 copy_map_value_locked(map, value, ptr, true);
798 else
799 copy_map_value(map, value, ptr);
800 /* mask lock, since value wasn't zero inited */
801 check_and_init_map_lock(map, value);
Prashant Bhole509db282018-10-09 10:04:49 +0900802 }
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800803 rcu_read_unlock();
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800804 }
Martin KaFai Lau7c4cd052019-01-30 18:12:45 -0800805 this_cpu_dec(bpf_prog_active);
806 preempt_enable();
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800807
Martin KaFai Lau7c4cd052019-01-30 18:12:45 -0800808done:
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800809 if (err)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800810 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700811
812 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800813 if (copy_to_user(uvalue, value, value_size) != 0)
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800814 goto free_value;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700815
816 err = 0;
817
Alexei Starovoitov8ebe6672015-01-22 17:11:08 -0800818free_value:
819 kfree(value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700820free_key:
821 kfree(key);
822err_put:
823 fdput(f);
824 return err;
825}
826
Daniel Colascione1ae80cf2018-10-12 03:54:27 -0700827static void maybe_wait_bpf_programs(struct bpf_map *map)
828{
829 /* Wait for any running BPF programs to complete so that
830 * userspace, when we return to it, knows that all programs
831 * that could be running use the new map value.
832 */
833 if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
834 map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS)
835 synchronize_rcu();
836}
837
Alexei Starovoitov3274f522014-11-13 17:36:44 -0800838#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700839
840static int map_update_elem(union bpf_attr *attr)
841{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100842 void __user *ukey = u64_to_user_ptr(attr->key);
843 void __user *uvalue = u64_to_user_ptr(attr->value);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700844 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700845 struct bpf_map *map;
846 void *key, *value;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800847 u32 value_size;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200848 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700849 int err;
850
851 if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM))
852 return -EINVAL;
853
Daniel Borkmann592867b2015-09-08 18:00:09 +0200854 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100855 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700856 if (IS_ERR(map))
857 return PTR_ERR(map);
858
Chenbo Feng6e71b042017-10-18 13:00:22 -0700859 if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
860 err = -EPERM;
861 goto err_put;
862 }
863
Alexei Starovoitov96049f32019-01-31 15:40:09 -0800864 if ((attr->flags & BPF_F_LOCK) &&
865 !map_value_has_spin_lock(map)) {
866 err = -EINVAL;
867 goto err_put;
868 }
869
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +0200870 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -0400871 if (IS_ERR(key)) {
872 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700873 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -0400874 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700875
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800876 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800877 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
Roman Gushchinb741f162018-09-28 14:45:43 +0000878 map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
879 map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800880 value_size = round_up(map->value_size, 8) * num_possible_cpus();
881 else
882 value_size = map->value_size;
883
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700884 err = -ENOMEM;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800885 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700886 if (!value)
887 goto free_key;
888
889 err = -EFAULT;
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800890 if (copy_from_user(value, uvalue, value_size) != 0)
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700891 goto free_value;
892
Jesper Dangaard Brouer6710e112017-10-16 12:19:28 +0200893 /* Need to create a kthread, thus must support schedule */
Jakub Kicinskia3884572018-01-11 20:29:09 -0800894 if (bpf_map_is_dev_bound(map)) {
895 err = bpf_map_offload_update_elem(map, key, value, attr->flags);
896 goto out;
John Fastabend99ba2b52018-07-05 08:50:04 -0700897 } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
898 map->map_type == BPF_MAP_TYPE_SOCKHASH ||
899 map->map_type == BPF_MAP_TYPE_SOCKMAP) {
Jesper Dangaard Brouer6710e112017-10-16 12:19:28 +0200900 err = map->ops->map_update_elem(map, key, value, attr->flags);
901 goto out;
902 }
903
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800904 /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
905 * inside bpf map update or delete otherwise deadlocks are possible
906 */
907 preempt_disable();
908 __this_cpu_inc(bpf_prog_active);
Martin KaFai Lau8f844932016-11-11 10:55:10 -0800909 if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
910 map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800911 err = bpf_percpu_hash_update(map, key, value, attr->flags);
912 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
913 err = bpf_percpu_array_update(map, key, value, attr->flags);
Roman Gushchinb741f162018-09-28 14:45:43 +0000914 } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
915 err = bpf_percpu_cgroup_storage_update(map, key, value,
916 attr->flags);
Mickaël Salaün9c147b52018-01-26 00:54:02 +0100917 } else if (IS_FD_ARRAY(map)) {
Daniel Borkmannd056a782016-06-15 22:47:13 +0200918 rcu_read_lock();
919 err = bpf_fd_array_map_update_elem(map, f.file, key, value,
920 attr->flags);
921 rcu_read_unlock();
Martin KaFai Laubcc6b1b2017-03-22 10:00:34 -0700922 } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
923 rcu_read_lock();
924 err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
925 attr->flags);
926 rcu_read_unlock();
Martin KaFai Lau5dc4c4b2018-08-08 01:01:24 -0700927 } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
928 /* rcu_read_lock() is not needed */
929 err = bpf_fd_reuseport_array_update_elem(map, key, value,
930 attr->flags);
Mauricio Vasquez Bf1a2e442018-10-18 15:16:25 +0200931 } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
932 map->map_type == BPF_MAP_TYPE_STACK) {
933 err = map->ops->map_push_elem(map, value, attr->flags);
Alexei Starovoitov15a07b32016-02-01 22:39:55 -0800934 } else {
935 rcu_read_lock();
936 err = map->ops->map_update_elem(map, key, value, attr->flags);
937 rcu_read_unlock();
938 }
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800939 __this_cpu_dec(bpf_prog_active);
940 preempt_enable();
Daniel Colascione1ae80cf2018-10-12 03:54:27 -0700941 maybe_wait_bpf_programs(map);
Jesper Dangaard Brouer6710e112017-10-16 12:19:28 +0200942out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700943free_value:
944 kfree(value);
945free_key:
946 kfree(key);
947err_put:
948 fdput(f);
949 return err;
950}
951
952#define BPF_MAP_DELETE_ELEM_LAST_FIELD key
953
954static int map_delete_elem(union bpf_attr *attr)
955{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +0100956 void __user *ukey = u64_to_user_ptr(attr->key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700957 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700958 struct bpf_map *map;
Daniel Borkmann592867b2015-09-08 18:00:09 +0200959 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700960 void *key;
961 int err;
962
963 if (CHECK_ATTR(BPF_MAP_DELETE_ELEM))
964 return -EINVAL;
965
Daniel Borkmann592867b2015-09-08 18:00:09 +0200966 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +0100967 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700968 if (IS_ERR(map))
969 return PTR_ERR(map);
970
Chenbo Feng6e71b042017-10-18 13:00:22 -0700971 if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
972 err = -EPERM;
973 goto err_put;
974 }
975
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +0200976 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -0400977 if (IS_ERR(key)) {
978 err = PTR_ERR(key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700979 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -0400980 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700981
Jakub Kicinskia3884572018-01-11 20:29:09 -0800982 if (bpf_map_is_dev_bound(map)) {
983 err = bpf_map_offload_delete_elem(map, key);
984 goto out;
985 }
986
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800987 preempt_disable();
988 __this_cpu_inc(bpf_prog_active);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700989 rcu_read_lock();
990 err = map->ops->map_delete_elem(map, key);
991 rcu_read_unlock();
Alexei Starovoitovb121d1e2016-03-07 21:57:13 -0800992 __this_cpu_dec(bpf_prog_active);
993 preempt_enable();
Daniel Colascione1ae80cf2018-10-12 03:54:27 -0700994 maybe_wait_bpf_programs(map);
Jakub Kicinskia3884572018-01-11 20:29:09 -0800995out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -0700996 kfree(key);
997err_put:
998 fdput(f);
999 return err;
1000}
1001
1002/* last field in 'union bpf_attr' used by this command */
1003#define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
1004
1005static int map_get_next_key(union bpf_attr *attr)
1006{
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001007 void __user *ukey = u64_to_user_ptr(attr->key);
1008 void __user *unext_key = u64_to_user_ptr(attr->next_key);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001009 int ufd = attr->map_fd;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001010 struct bpf_map *map;
1011 void *key, *next_key;
Daniel Borkmann592867b2015-09-08 18:00:09 +02001012 struct fd f;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001013 int err;
1014
1015 if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY))
1016 return -EINVAL;
1017
Daniel Borkmann592867b2015-09-08 18:00:09 +02001018 f = fdget(ufd);
Daniel Borkmannc2101292015-10-29 14:58:07 +01001019 map = __bpf_map_get(f);
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001020 if (IS_ERR(map))
1021 return PTR_ERR(map);
1022
Chenbo Feng6e71b042017-10-18 13:00:22 -07001023 if (!(f.file->f_mode & FMODE_CAN_READ)) {
1024 err = -EPERM;
1025 goto err_put;
1026 }
1027
Teng Qin8fe45922017-04-24 19:00:37 -07001028 if (ukey) {
Mauricio Vasquez Bc9d29f42018-10-18 15:16:14 +02001029 key = __bpf_copy_key(ukey, map->key_size);
Al Viroe4448ed2017-05-13 18:43:00 -04001030 if (IS_ERR(key)) {
1031 err = PTR_ERR(key);
Teng Qin8fe45922017-04-24 19:00:37 -07001032 goto err_put;
Al Viroe4448ed2017-05-13 18:43:00 -04001033 }
Teng Qin8fe45922017-04-24 19:00:37 -07001034 } else {
1035 key = NULL;
1036 }
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001037
1038 err = -ENOMEM;
1039 next_key = kmalloc(map->key_size, GFP_USER);
1040 if (!next_key)
1041 goto free_key;
1042
Jakub Kicinskia3884572018-01-11 20:29:09 -08001043 if (bpf_map_is_dev_bound(map)) {
1044 err = bpf_map_offload_get_next_key(map, key, next_key);
1045 goto out;
1046 }
1047
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001048 rcu_read_lock();
1049 err = map->ops->map_get_next_key(map, key, next_key);
1050 rcu_read_unlock();
Jakub Kicinskia3884572018-01-11 20:29:09 -08001051out:
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07001052 if (err)
1053 goto free_next_key;
1054
1055 err = -EFAULT;
1056 if (copy_to_user(unext_key, next_key, map->key_size) != 0)
1057 goto free_next_key;
1058
1059 err = 0;
1060
1061free_next_key:
1062 kfree(next_key);
1063free_key:
1064 kfree(key);
1065err_put:
1066 fdput(f);
1067 return err;
1068}
1069
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001070#define BPF_MAP_LOOKUP_AND_DELETE_ELEM_LAST_FIELD value
1071
1072static int map_lookup_and_delete_elem(union bpf_attr *attr)
1073{
1074 void __user *ukey = u64_to_user_ptr(attr->key);
1075 void __user *uvalue = u64_to_user_ptr(attr->value);
1076 int ufd = attr->map_fd;
1077 struct bpf_map *map;
Alexei Starovoitov540fefc2018-10-19 13:52:38 -07001078 void *key, *value;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02001079 u32 value_size;
1080 struct fd f;
1081 int err;
1082
1083 if (CHECK_ATTR(BPF_MAP_LOOKUP_AND_DELETE_ELEM))
1084 return -EINVAL;
1085
1086 f = fdget(ufd);
1087 map = __bpf_map_get(f);
1088 if (IS_ERR(map))
1089 return PTR_ERR(map);
1090
1091 if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
1092 err = -EPERM;
1093 goto err_put;
1094 }
1095
1096 key = __bpf_copy_key(ukey, map->key_size);
1097 if (IS_ERR(key)) {
1098 err = PTR_ERR(key);
1099 goto err_put;
1100 }
1101
1102 value_size = map->value_size;
1103
1104 err = -ENOMEM;
1105 value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
1106 if (!value)
1107 goto free_key;
1108
1109 if (map->map_type == BPF_MAP_TYPE_QUEUE ||
1110 map->map_type == BPF_MAP_TYPE_STACK) {
1111 err = map->ops->map_pop_elem(map, value);
1112 } else {
1113 err = -ENOTSUPP;
1114 }
1115
1116 if (err)
1117 goto free_value;
1118
1119 if (copy_to_user(uvalue, value, value_size) != 0)
1120 goto free_value;
1121
1122 err = 0;
1123
1124free_value:
1125 kfree(value);
1126free_key:
1127 kfree(key);
1128err_put:
1129 fdput(f);
1130 return err;
1131}
1132
Jakub Kicinski7de16e32017-10-16 16:40:53 -07001133static const struct bpf_prog_ops * const bpf_prog_types[] = {
1134#define BPF_PROG_TYPE(_id, _name) \
1135 [_id] = & _name ## _prog_ops,
1136#define BPF_MAP_TYPE(_id, _ops)
1137#include <linux/bpf_types.h>
1138#undef BPF_PROG_TYPE
1139#undef BPF_MAP_TYPE
1140};
1141
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001142static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
1143{
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001144 const struct bpf_prog_ops *ops;
1145
1146 if (type >= ARRAY_SIZE(bpf_prog_types))
1147 return -EINVAL;
1148 type = array_index_nospec(type, ARRAY_SIZE(bpf_prog_types));
1149 ops = bpf_prog_types[type];
1150 if (!ops)
Johannes Bergbe9370a2017-04-11 15:34:57 +02001151 return -EINVAL;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001152
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001153 if (!bpf_prog_is_dev_bound(prog->aux))
Daniel Borkmannd0f1a452018-05-04 02:13:57 +02001154 prog->aux->ops = ops;
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001155 else
1156 prog->aux->ops = &bpf_offload_prog_ops;
Johannes Bergbe9370a2017-04-11 15:34:57 +02001157 prog->type = type;
1158 return 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001159}
1160
1161/* drop refcnt on maps used by eBPF program and free auxilary data */
1162static void free_used_maps(struct bpf_prog_aux *aux)
1163{
Roman Gushchin8bad74f2018-09-28 14:45:36 +00001164 enum bpf_cgroup_storage_type stype;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001165 int i;
1166
Roman Gushchin8bad74f2018-09-28 14:45:36 +00001167 for_each_cgroup_storage_type(stype) {
1168 if (!aux->cgroup_storage[stype])
1169 continue;
1170 bpf_cgroup_storage_release(aux->prog,
1171 aux->cgroup_storage[stype]);
1172 }
Roman Gushchinde9cbba2018-08-02 14:27:18 -07001173
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001174 for (i = 0; i < aux->used_map_cnt; i++)
1175 bpf_map_put(aux->used_maps[i]);
1176
1177 kfree(aux->used_maps);
1178}
1179
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001180int __bpf_prog_charge(struct user_struct *user, u32 pages)
1181{
1182 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
1183 unsigned long user_bufs;
1184
1185 if (user) {
1186 user_bufs = atomic_long_add_return(pages, &user->locked_vm);
1187 if (user_bufs > memlock_limit) {
1188 atomic_long_sub(pages, &user->locked_vm);
1189 return -EPERM;
1190 }
1191 }
1192
1193 return 0;
1194}
1195
1196void __bpf_prog_uncharge(struct user_struct *user, u32 pages)
1197{
1198 if (user)
1199 atomic_long_sub(pages, &user->locked_vm);
1200}
1201
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001202static int bpf_prog_charge_memlock(struct bpf_prog *prog)
1203{
1204 struct user_struct *user = get_current_user();
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001205 int ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001206
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001207 ret = __bpf_prog_charge(user, prog->pages);
1208 if (ret) {
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001209 free_uid(user);
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001210 return ret;
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001211 }
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001212
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001213 prog->aux->user = user;
1214 return 0;
1215}
1216
1217static void bpf_prog_uncharge_memlock(struct bpf_prog *prog)
1218{
1219 struct user_struct *user = prog->aux->user;
1220
Daniel Borkmann5ccb0712016-12-18 01:52:58 +01001221 __bpf_prog_uncharge(user, prog->pages);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001222 free_uid(user);
1223}
1224
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001225static int bpf_prog_alloc_id(struct bpf_prog *prog)
1226{
1227 int id;
1228
Shaohua Lib76354c2018-03-27 11:53:21 -07001229 idr_preload(GFP_KERNEL);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001230 spin_lock_bh(&prog_idr_lock);
1231 id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
1232 if (id > 0)
1233 prog->aux->id = id;
1234 spin_unlock_bh(&prog_idr_lock);
Shaohua Lib76354c2018-03-27 11:53:21 -07001235 idr_preload_end();
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001236
1237 /* id is in [1, INT_MAX) */
1238 if (WARN_ON_ONCE(!id))
1239 return -ENOSPC;
1240
1241 return id > 0 ? 0 : id;
1242}
1243
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001244void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001245{
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001246 /* cBPF to eBPF migrations are currently not in the idr store.
1247 * Offloaded programs are removed from the store when their device
1248 * disappears - even if someone grabs an fd to them they are unusable,
1249 * simply waiting for refcnt to drop to be freed.
1250 */
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001251 if (!prog->aux->id)
1252 return;
1253
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001254 if (do_idr_lock)
1255 spin_lock_bh(&prog_idr_lock);
1256 else
1257 __acquire(&prog_idr_lock);
1258
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001259 idr_remove(&prog_idr, prog->aux->id);
Jakub Kicinskiad8ad792017-12-27 18:39:07 -08001260 prog->aux->id = 0;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001261
1262 if (do_idr_lock)
1263 spin_unlock_bh(&prog_idr_lock);
1264 else
1265 __release(&prog_idr_lock);
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001266}
1267
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001268static void __bpf_prog_put_rcu(struct rcu_head *rcu)
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001269{
1270 struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
1271
1272 free_used_maps(aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001273 bpf_prog_uncharge_memlock(aux->prog);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001274 security_bpf_prog_free(aux);
Alexei Starovoitovabf2e7d2015-05-28 19:26:02 -07001275 bpf_prog_free(aux->prog);
1276}
1277
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001278static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001279{
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01001280 if (atomic_dec_and_test(&prog->aux->refcnt)) {
Song Liu6ee52e22019-01-17 08:15:15 -08001281 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001282 /* bpf_prog_free_id() must be called first */
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001283 bpf_prog_free_id(prog, do_idr_lock);
Daniel Borkmann7d1982b2018-06-15 02:30:47 +02001284 bpf_prog_kallsyms_del_all(prog);
Yonghong Song838e9692018-11-19 15:29:11 -08001285 btf_put(prog->aux->btf);
Yonghong Songba64e7d2018-11-24 23:20:44 -08001286 kvfree(prog->aux->func_info);
Martin KaFai Lauc454a462018-12-07 16:42:25 -08001287 bpf_prog_free_linfo(prog);
Daniel Borkmann4f74d802017-12-20 13:42:56 +01001288
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001289 call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
Daniel Borkmanna67edbf2017-01-25 02:28:18 +01001290 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001291}
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001292
1293void bpf_prog_put(struct bpf_prog *prog)
1294{
1295 __bpf_prog_put(prog, true);
1296}
Daniel Borkmanne2e9b652015-03-01 12:31:48 +01001297EXPORT_SYMBOL_GPL(bpf_prog_put);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001298
1299static int bpf_prog_release(struct inode *inode, struct file *filp)
1300{
1301 struct bpf_prog *prog = filp->private_data;
1302
Daniel Borkmann1aacde32016-06-30 17:24:43 +02001303 bpf_prog_put(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001304 return 0;
1305}
1306
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001307static void bpf_prog_get_stats(const struct bpf_prog *prog,
1308 struct bpf_prog_stats *stats)
1309{
1310 u64 nsecs = 0, cnt = 0;
1311 int cpu;
1312
1313 for_each_possible_cpu(cpu) {
1314 const struct bpf_prog_stats *st;
1315 unsigned int start;
1316 u64 tnsecs, tcnt;
1317
1318 st = per_cpu_ptr(prog->aux->stats, cpu);
1319 do {
1320 start = u64_stats_fetch_begin_irq(&st->syncp);
1321 tnsecs = st->nsecs;
1322 tcnt = st->cnt;
1323 } while (u64_stats_fetch_retry_irq(&st->syncp, start));
1324 nsecs += tnsecs;
1325 cnt += tcnt;
1326 }
1327 stats->nsecs = nsecs;
1328 stats->cnt = cnt;
1329}
1330
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001331#ifdef CONFIG_PROC_FS
1332static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
1333{
1334 const struct bpf_prog *prog = filp->private_data;
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001335 char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001336 struct bpf_prog_stats stats;
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001337
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001338 bpf_prog_get_stats(prog, &stats);
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001339 bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001340 seq_printf(m,
1341 "prog_type:\t%u\n"
1342 "prog_jited:\t%u\n"
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001343 "prog_tag:\t%s\n"
Daniel Borkmann4316b402018-06-02 23:06:34 +02001344 "memlock:\t%llu\n"
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001345 "prog_id:\t%u\n"
1346 "run_time_ns:\t%llu\n"
1347 "run_cnt:\t%llu\n",
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001348 prog->type,
1349 prog->jited,
Daniel Borkmannf1f77142017-01-13 23:38:15 +01001350 prog_tag,
Daniel Borkmann4316b402018-06-02 23:06:34 +02001351 prog->pages * 1ULL << PAGE_SHIFT,
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001352 prog->aux->id,
1353 stats.nsecs,
1354 stats.cnt);
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001355}
1356#endif
1357
Chenbo Fengf66e4482017-10-18 13:00:26 -07001358const struct file_operations bpf_prog_fops = {
Daniel Borkmann7bd509e2016-12-04 23:19:41 +01001359#ifdef CONFIG_PROC_FS
1360 .show_fdinfo = bpf_prog_show_fdinfo,
1361#endif
1362 .release = bpf_prog_release,
Chenbo Feng6e71b042017-10-18 13:00:22 -07001363 .read = bpf_dummy_read,
1364 .write = bpf_dummy_write,
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001365};
1366
Daniel Borkmannb2197752015-10-29 14:58:09 +01001367int bpf_prog_new_fd(struct bpf_prog *prog)
Daniel Borkmannaa797812015-10-29 14:58:06 +01001368{
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001369 int ret;
1370
1371 ret = security_bpf_prog(prog);
1372 if (ret < 0)
1373 return ret;
1374
Daniel Borkmannaa797812015-10-29 14:58:06 +01001375 return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog,
1376 O_RDWR | O_CLOEXEC);
1377}
1378
Daniel Borkmann113214b2016-06-30 17:24:44 +02001379static struct bpf_prog *____bpf_prog_get(struct fd f)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001380{
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001381 if (!f.file)
1382 return ERR_PTR(-EBADF);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001383 if (f.file->f_op != &bpf_prog_fops) {
1384 fdput(f);
1385 return ERR_PTR(-EINVAL);
1386 }
1387
Daniel Borkmannc2101292015-10-29 14:58:07 +01001388 return f.file->private_data;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001389}
1390
Brenden Blanco59d36562016-07-19 12:16:46 -07001391struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001392{
Brenden Blanco59d36562016-07-19 12:16:46 -07001393 if (atomic_add_return(i, &prog->aux->refcnt) > BPF_MAX_REFCNT) {
1394 atomic_sub(i, &prog->aux->refcnt);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001395 return ERR_PTR(-EBUSY);
1396 }
1397 return prog;
1398}
Brenden Blanco59d36562016-07-19 12:16:46 -07001399EXPORT_SYMBOL_GPL(bpf_prog_add);
1400
Daniel Borkmannc5405942016-11-09 22:02:34 +01001401void bpf_prog_sub(struct bpf_prog *prog, int i)
1402{
1403 /* Only to be used for undoing previous bpf_prog_add() in some
1404 * error path. We still know that another entity in our call
1405 * path holds a reference to the program, thus atomic_sub() can
1406 * be safely used in such cases!
1407 */
1408 WARN_ON(atomic_sub_return(i, &prog->aux->refcnt) == 0);
1409}
1410EXPORT_SYMBOL_GPL(bpf_prog_sub);
1411
Brenden Blanco59d36562016-07-19 12:16:46 -07001412struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
1413{
1414 return bpf_prog_add(prog, 1);
1415}
Daniel Borkmann97bc4022016-11-19 01:45:00 +01001416EXPORT_SYMBOL_GPL(bpf_prog_inc);
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001417
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001418/* prog_idr_lock should have been held */
John Fastabenda6f6df62017-08-15 22:32:22 -07001419struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001420{
1421 int refold;
1422
Mark Rutlandbfc18e32018-06-21 13:13:04 +01001423 refold = atomic_fetch_add_unless(&prog->aux->refcnt, 1, 0);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001424
1425 if (refold >= BPF_MAX_REFCNT) {
1426 __bpf_prog_put(prog, false);
1427 return ERR_PTR(-EBUSY);
1428 }
1429
1430 if (!refold)
1431 return ERR_PTR(-ENOENT);
1432
1433 return prog;
1434}
John Fastabenda6f6df62017-08-15 22:32:22 -07001435EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001436
Al Viro040ee692017-12-02 20:20:38 -05001437bool bpf_prog_get_ok(struct bpf_prog *prog,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001438 enum bpf_prog_type *attach_type, bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001439{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001440 /* not an attachment, just a refcount inc, always allow */
1441 if (!attach_type)
1442 return true;
Jakub Kicinski248f3462017-11-03 13:56:20 -07001443
1444 if (prog->type != *attach_type)
1445 return false;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001446 if (bpf_prog_is_dev_bound(prog->aux) && !attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001447 return false;
1448
1449 return true;
1450}
1451
1452static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001453 bool attach_drv)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001454{
1455 struct fd f = fdget(ufd);
1456 struct bpf_prog *prog;
1457
Daniel Borkmann113214b2016-06-30 17:24:44 +02001458 prog = ____bpf_prog_get(f);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001459 if (IS_ERR(prog))
1460 return prog;
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001461 if (!bpf_prog_get_ok(prog, attach_type, attach_drv)) {
Daniel Borkmann113214b2016-06-30 17:24:44 +02001462 prog = ERR_PTR(-EINVAL);
1463 goto out;
1464 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001465
Alexei Starovoitov92117d82016-04-27 18:56:20 -07001466 prog = bpf_prog_inc(prog);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001467out:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001468 fdput(f);
1469 return prog;
1470}
Daniel Borkmann113214b2016-06-30 17:24:44 +02001471
1472struct bpf_prog *bpf_prog_get(u32 ufd)
1473{
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001474 return __bpf_prog_get(ufd, NULL, false);
Daniel Borkmann113214b2016-06-30 17:24:44 +02001475}
1476
Jakub Kicinski248f3462017-11-03 13:56:20 -07001477struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type,
Jakub Kicinski288b3de2017-11-20 15:21:54 -08001478 bool attach_drv)
Jakub Kicinski248f3462017-11-03 13:56:20 -07001479{
Alexei Starovoitov4d220ed2018-04-28 19:56:37 -07001480 return __bpf_prog_get(ufd, &type, attach_drv);
Jakub Kicinski248f3462017-11-03 13:56:20 -07001481}
Jakub Kicinski6c8dfe22017-11-03 13:56:21 -07001482EXPORT_SYMBOL_GPL(bpf_prog_get_type_dev);
Jakub Kicinski248f3462017-11-03 13:56:20 -07001483
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001484/* Initially all BPF programs could be loaded w/o specifying
1485 * expected_attach_type. Later for some of them specifying expected_attach_type
1486 * at load time became required so that program could be validated properly.
1487 * Programs of types that are allowed to be loaded both w/ and w/o (for
1488 * backward compatibility) expected_attach_type, should have the default attach
1489 * type assigned to expected_attach_type for the latter case, so that it can be
1490 * validated later at attach time.
1491 *
1492 * bpf_prog_load_fixup_attach_type() sets expected_attach_type in @attr if
1493 * prog type requires it but has some attach types that have to be backward
1494 * compatible.
1495 */
1496static void bpf_prog_load_fixup_attach_type(union bpf_attr *attr)
1497{
1498 switch (attr->prog_type) {
1499 case BPF_PROG_TYPE_CGROUP_SOCK:
1500 /* Unfortunately BPF_ATTACH_TYPE_UNSPEC enumeration doesn't
1501 * exist so checking for non-zero is the way to go here.
1502 */
1503 if (!attr->expected_attach_type)
1504 attr->expected_attach_type =
1505 BPF_CGROUP_INET_SOCK_CREATE;
1506 break;
1507 }
1508}
1509
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001510static int
1511bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
1512 enum bpf_attach_type expected_attach_type)
1513{
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001514 switch (prog_type) {
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001515 case BPF_PROG_TYPE_CGROUP_SOCK:
1516 switch (expected_attach_type) {
1517 case BPF_CGROUP_INET_SOCK_CREATE:
1518 case BPF_CGROUP_INET4_POST_BIND:
1519 case BPF_CGROUP_INET6_POST_BIND:
1520 return 0;
1521 default:
1522 return -EINVAL;
1523 }
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001524 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
1525 switch (expected_attach_type) {
1526 case BPF_CGROUP_INET4_BIND:
1527 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07001528 case BPF_CGROUP_INET4_CONNECT:
1529 case BPF_CGROUP_INET6_CONNECT:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07001530 case BPF_CGROUP_UDP4_SENDMSG:
1531 case BPF_CGROUP_UDP6_SENDMSG:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001532 return 0;
1533 default:
1534 return -EINVAL;
1535 }
1536 default:
1537 return 0;
1538 }
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001539}
1540
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001541/* last field in 'union bpf_attr' used by this command */
Martin KaFai Lauc454a462018-12-07 16:42:25 -08001542#define BPF_PROG_LOAD_LAST_FIELD line_info_cnt
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001543
Yonghong Song838e9692018-11-19 15:29:11 -08001544static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001545{
1546 enum bpf_prog_type type = attr->prog_type;
1547 struct bpf_prog *prog;
1548 int err;
1549 char license[128];
1550 bool is_gpl;
1551
1552 if (CHECK_ATTR(BPF_PROG_LOAD))
1553 return -EINVAL;
1554
David Millere9ee9ef2018-11-30 21:08:14 -08001555 if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT | BPF_F_ANY_ALIGNMENT))
David S. Millere07b98d2017-05-10 11:38:07 -07001556 return -EINVAL;
1557
David Millere9ee9ef2018-11-30 21:08:14 -08001558 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
1559 (attr->prog_flags & BPF_F_ANY_ALIGNMENT) &&
1560 !capable(CAP_SYS_ADMIN))
1561 return -EPERM;
1562
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001563 /* copy eBPF program license from user space */
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001564 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001565 sizeof(license) - 1) < 0)
1566 return -EFAULT;
1567 license[sizeof(license) - 1] = 0;
1568
1569 /* eBPF programs must be GPL compatible to use GPL-ed functions */
1570 is_gpl = license_is_gpl_compatible(license);
1571
Alexei Starovoitovc04c0d22019-04-01 21:27:45 -07001572 if (attr->insn_cnt == 0 ||
1573 attr->insn_cnt > (capable(CAP_SYS_ADMIN) ? BPF_COMPLEXITY_LIMIT_INSNS : BPF_MAXINSNS))
Daniel Borkmannef0915c2016-12-07 01:15:44 +01001574 return -E2BIG;
Chenbo Feng80b7d812017-05-31 18:16:00 -07001575 if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
1576 type != BPF_PROG_TYPE_CGROUP_SKB &&
1577 !capable(CAP_SYS_ADMIN))
Alexei Starovoitov1be7f752015-10-07 22:23:21 -07001578 return -EPERM;
1579
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001580 bpf_prog_load_fixup_attach_type(attr);
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001581 if (bpf_prog_load_check_attach_type(type, attr->expected_attach_type))
1582 return -EINVAL;
1583
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001584 /* plain bpf_prog allocation */
1585 prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER);
1586 if (!prog)
1587 return -ENOMEM;
1588
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001589 prog->expected_attach_type = attr->expected_attach_type;
1590
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08001591 prog->aux->offload_requested = !!attr->prog_ifindex;
1592
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001593 err = security_bpf_prog_alloc(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001594 if (err)
1595 goto free_prog_nouncharge;
1596
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001597 err = bpf_prog_charge_memlock(prog);
1598 if (err)
1599 goto free_prog_sec;
1600
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001601 prog->len = attr->insn_cnt;
1602
1603 err = -EFAULT;
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001604 if (copy_from_user(prog->insns, u64_to_user_ptr(attr->insns),
Daniel Borkmannaafe6ae2016-12-18 01:52:57 +01001605 bpf_prog_insn_size(prog)) != 0)
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001606 goto free_prog;
1607
1608 prog->orig_prog = NULL;
Daniel Borkmanna91263d2015-09-30 01:41:50 +02001609 prog->jited = 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001610
1611 atomic_set(&prog->aux->refcnt, 1);
Daniel Borkmanna91263d2015-09-30 01:41:50 +02001612 prog->gpl_compatible = is_gpl ? 1 : 0;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001613
Jakub Kicinski9a18eed2017-12-27 18:39:04 -08001614 if (bpf_prog_is_dev_bound(prog->aux)) {
Jakub Kicinskiab3f0062017-11-03 13:56:17 -07001615 err = bpf_prog_offload_init(prog, attr);
1616 if (err)
1617 goto free_prog;
1618 }
1619
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001620 /* find program type: socket_filter vs tracing_filter */
1621 err = find_prog_type(type, prog);
1622 if (err < 0)
1623 goto free_prog;
1624
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07001625 prog->aux->load_time = ktime_get_boot_ns();
1626 err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name);
1627 if (err)
1628 goto free_prog;
1629
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001630 /* run eBPF verifier */
Yonghong Song838e9692018-11-19 15:29:11 -08001631 err = bpf_check(&prog, attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001632 if (err < 0)
1633 goto free_used_maps;
1634
Daniel Borkmann9facc332018-06-15 02:30:48 +02001635 prog = bpf_prog_select_runtime(prog, &err);
Alexei Starovoitov04fd61ab2015-05-19 16:59:03 -07001636 if (err < 0)
1637 goto free_used_maps;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001638
Martin KaFai Laudc4bb0e2017-06-05 12:15:46 -07001639 err = bpf_prog_alloc_id(prog);
1640 if (err)
1641 goto free_used_maps;
1642
Daniel Borkmannaa797812015-10-29 14:58:06 +01001643 err = bpf_prog_new_fd(prog);
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07001644 if (err < 0) {
1645 /* failed to allocate fd.
1646 * bpf_prog_put() is needed because the above
1647 * bpf_prog_alloc_id() has published the prog
1648 * to the userspace and the userspace may
1649 * have refcnt-ed it through BPF_PROG_GET_FD_BY_ID.
1650 */
1651 bpf_prog_put(prog);
1652 return err;
1653 }
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001654
Daniel Borkmann74451e662017-02-16 22:24:50 +01001655 bpf_prog_kallsyms_add(prog);
Song Liu6ee52e22019-01-17 08:15:15 -08001656 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001657 return err;
1658
1659free_used_maps:
Martin KaFai Lauc454a462018-12-07 16:42:25 -08001660 bpf_prog_free_linfo(prog);
Martin KaFai Lau5482e9a2018-12-01 17:08:44 -08001661 kvfree(prog->aux->func_info);
1662 btf_put(prog->aux->btf);
Daniel Borkmann7d1982b2018-06-15 02:30:47 +02001663 bpf_prog_kallsyms_del_subprogs(prog);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001664 free_used_maps(prog->aux);
1665free_prog:
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001666 bpf_prog_uncharge_memlock(prog);
Chenbo Fengafdb09c2017-10-18 13:00:24 -07001667free_prog_sec:
1668 security_bpf_prog_free(prog->aux);
Alexei Starovoitovaaac3ba2015-10-07 22:23:22 -07001669free_prog_nouncharge:
Alexei Starovoitov09756af2014-09-26 00:17:00 -07001670 bpf_prog_free(prog);
1671 return err;
1672}
1673
Chenbo Feng6e71b042017-10-18 13:00:22 -07001674#define BPF_OBJ_LAST_FIELD file_flags
Daniel Borkmannb2197752015-10-29 14:58:09 +01001675
1676static int bpf_obj_pin(const union bpf_attr *attr)
1677{
Chenbo Feng6e71b042017-10-18 13:00:22 -07001678 if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0)
Daniel Borkmannb2197752015-10-29 14:58:09 +01001679 return -EINVAL;
1680
Mickaël Salaün535e7b4b2016-11-13 19:44:03 +01001681 return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname));
Daniel Borkmannb2197752015-10-29 14:58:09 +01001682}
1683
1684static int bpf_obj_get(const union bpf_attr *attr)
1685{
Chenbo Feng6e71b042017-10-18 13:00:22 -07001686 if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0 ||
1687 attr->file_flags & ~BPF_OBJ_FLAG_MASK)
Daniel Borkmannb2197752015-10-29 14:58:09 +01001688 return -EINVAL;
1689
Chenbo Feng6e71b042017-10-18 13:00:22 -07001690 return bpf_obj_get_user(u64_to_user_ptr(attr->pathname),
1691 attr->file_flags);
Daniel Borkmannb2197752015-10-29 14:58:09 +01001692}
1693
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07001694struct bpf_raw_tracepoint {
1695 struct bpf_raw_event_map *btp;
1696 struct bpf_prog *prog;
1697};
1698
1699static int bpf_raw_tracepoint_release(struct inode *inode, struct file *filp)
1700{
1701 struct bpf_raw_tracepoint *raw_tp = filp->private_data;
1702
1703 if (raw_tp->prog) {
1704 bpf_probe_unregister(raw_tp->btp, raw_tp->prog);
1705 bpf_prog_put(raw_tp->prog);
1706 }
Matt Mullinsa38d1102018-12-12 16:42:37 -08001707 bpf_put_raw_tracepoint(raw_tp->btp);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07001708 kfree(raw_tp);
1709 return 0;
1710}
1711
1712static const struct file_operations bpf_raw_tp_fops = {
1713 .release = bpf_raw_tracepoint_release,
1714 .read = bpf_dummy_read,
1715 .write = bpf_dummy_write,
1716};
1717
1718#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
1719
1720static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
1721{
1722 struct bpf_raw_tracepoint *raw_tp;
1723 struct bpf_raw_event_map *btp;
1724 struct bpf_prog *prog;
1725 char tp_name[128];
1726 int tp_fd, err;
1727
1728 if (strncpy_from_user(tp_name, u64_to_user_ptr(attr->raw_tracepoint.name),
1729 sizeof(tp_name) - 1) < 0)
1730 return -EFAULT;
1731 tp_name[sizeof(tp_name) - 1] = 0;
1732
Matt Mullinsa38d1102018-12-12 16:42:37 -08001733 btp = bpf_get_raw_tracepoint(tp_name);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07001734 if (!btp)
1735 return -ENOENT;
1736
1737 raw_tp = kzalloc(sizeof(*raw_tp), GFP_USER);
Matt Mullinsa38d1102018-12-12 16:42:37 -08001738 if (!raw_tp) {
1739 err = -ENOMEM;
1740 goto out_put_btp;
1741 }
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07001742 raw_tp->btp = btp;
1743
1744 prog = bpf_prog_get_type(attr->raw_tracepoint.prog_fd,
1745 BPF_PROG_TYPE_RAW_TRACEPOINT);
1746 if (IS_ERR(prog)) {
1747 err = PTR_ERR(prog);
1748 goto out_free_tp;
1749 }
1750
1751 err = bpf_probe_register(raw_tp->btp, prog);
1752 if (err)
1753 goto out_put_prog;
1754
1755 raw_tp->prog = prog;
1756 tp_fd = anon_inode_getfd("bpf-raw-tracepoint", &bpf_raw_tp_fops, raw_tp,
1757 O_CLOEXEC);
1758 if (tp_fd < 0) {
1759 bpf_probe_unregister(raw_tp->btp, prog);
1760 err = tp_fd;
1761 goto out_put_prog;
1762 }
1763 return tp_fd;
1764
1765out_put_prog:
1766 bpf_prog_put(prog);
1767out_free_tp:
1768 kfree(raw_tp);
Matt Mullinsa38d1102018-12-12 16:42:37 -08001769out_put_btp:
1770 bpf_put_raw_tracepoint(btp);
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07001771 return err;
1772}
1773
Anders Roxell33491582018-04-03 14:09:47 +02001774static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
1775 enum bpf_attach_type attach_type)
1776{
1777 switch (prog->type) {
1778 case BPF_PROG_TYPE_CGROUP_SOCK:
1779 case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
1780 return attach_type == prog->expected_attach_type ? 0 : -EINVAL;
1781 default:
1782 return 0;
1783 }
1784}
1785
John Fastabend464bc0f2017-08-28 07:10:04 -07001786#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
John Fastabend174a79f2017-08-15 22:32:47 -07001787
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07001788#define BPF_F_ATTACH_MASK \
1789 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI)
1790
Daniel Mackf4324552016-11-23 16:52:27 +01001791static int bpf_prog_attach(const union bpf_attr *attr)
1792{
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001793 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01001794 struct bpf_prog *prog;
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001795 int ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001796
1797 if (!capable(CAP_NET_ADMIN))
1798 return -EPERM;
1799
1800 if (CHECK_ATTR(BPF_PROG_ATTACH))
1801 return -EINVAL;
1802
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07001803 if (attr->attach_flags & ~BPF_F_ATTACH_MASK)
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001804 return -EINVAL;
1805
Daniel Mackf4324552016-11-23 16:52:27 +01001806 switch (attr->attach_type) {
1807 case BPF_CGROUP_INET_INGRESS:
1808 case BPF_CGROUP_INET_EGRESS:
David Ahernb2cd1252016-12-01 08:48:03 -08001809 ptype = BPF_PROG_TYPE_CGROUP_SKB;
Daniel Mackf4324552016-11-23 16:52:27 +01001810 break;
David Ahern610236582016-12-01 08:48:04 -08001811 case BPF_CGROUP_INET_SOCK_CREATE:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001812 case BPF_CGROUP_INET4_POST_BIND:
1813 case BPF_CGROUP_INET6_POST_BIND:
David Ahern610236582016-12-01 08:48:04 -08001814 ptype = BPF_PROG_TYPE_CGROUP_SOCK;
1815 break;
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001816 case BPF_CGROUP_INET4_BIND:
1817 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07001818 case BPF_CGROUP_INET4_CONNECT:
1819 case BPF_CGROUP_INET6_CONNECT:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07001820 case BPF_CGROUP_UDP4_SENDMSG:
1821 case BPF_CGROUP_UDP6_SENDMSG:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001822 ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
1823 break;
Lawrence Brakmo40304b22017-06-30 20:02:40 -07001824 case BPF_CGROUP_SOCK_OPS:
1825 ptype = BPF_PROG_TYPE_SOCK_OPS;
1826 break;
Roman Gushchinebc614f2017-11-05 08:15:32 -05001827 case BPF_CGROUP_DEVICE:
1828 ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
1829 break;
John Fastabend4f738ad2018-03-18 12:57:10 -07001830 case BPF_SK_MSG_VERDICT:
Sean Youngfdb5c452018-06-19 00:04:24 +01001831 ptype = BPF_PROG_TYPE_SK_MSG;
1832 break;
John Fastabend464bc0f2017-08-28 07:10:04 -07001833 case BPF_SK_SKB_STREAM_PARSER:
1834 case BPF_SK_SKB_STREAM_VERDICT:
Sean Youngfdb5c452018-06-19 00:04:24 +01001835 ptype = BPF_PROG_TYPE_SK_SKB;
1836 break;
Sean Youngf4364dc2018-05-27 12:24:09 +01001837 case BPF_LIRC_MODE2:
Sean Youngfdb5c452018-06-19 00:04:24 +01001838 ptype = BPF_PROG_TYPE_LIRC_MODE2;
1839 break;
Petar Penkovd58e4682018-09-14 07:46:18 -07001840 case BPF_FLOW_DISSECTOR:
1841 ptype = BPF_PROG_TYPE_FLOW_DISSECTOR;
1842 break;
Daniel Mackf4324552016-11-23 16:52:27 +01001843 default:
1844 return -EINVAL;
1845 }
1846
David Ahernb2cd1252016-12-01 08:48:03 -08001847 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
1848 if (IS_ERR(prog))
1849 return PTR_ERR(prog);
1850
Andrey Ignatov5e43f892018-03-30 15:08:00 -07001851 if (bpf_prog_attach_check_attach_type(prog, attr->attach_type)) {
1852 bpf_prog_put(prog);
1853 return -EINVAL;
1854 }
1855
Sean Youngfdb5c452018-06-19 00:04:24 +01001856 switch (ptype) {
1857 case BPF_PROG_TYPE_SK_SKB:
1858 case BPF_PROG_TYPE_SK_MSG:
Daniel Borkmann604326b2018-10-13 02:45:58 +02001859 ret = sock_map_get_from_fd(attr, prog);
Sean Youngfdb5c452018-06-19 00:04:24 +01001860 break;
1861 case BPF_PROG_TYPE_LIRC_MODE2:
1862 ret = lirc_prog_attach(attr, prog);
1863 break;
Petar Penkovd58e4682018-09-14 07:46:18 -07001864 case BPF_PROG_TYPE_FLOW_DISSECTOR:
1865 ret = skb_flow_dissector_bpf_prog_attach(attr, prog);
1866 break;
Sean Youngfdb5c452018-06-19 00:04:24 +01001867 default:
1868 ret = cgroup_bpf_prog_attach(attr, ptype, prog);
David Ahernb2cd1252016-12-01 08:48:03 -08001869 }
1870
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001871 if (ret)
1872 bpf_prog_put(prog);
Alexei Starovoitov7f677632017-02-10 20:28:24 -08001873 return ret;
Daniel Mackf4324552016-11-23 16:52:27 +01001874}
1875
1876#define BPF_PROG_DETACH_LAST_FIELD attach_type
1877
1878static int bpf_prog_detach(const union bpf_attr *attr)
1879{
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07001880 enum bpf_prog_type ptype;
Daniel Mackf4324552016-11-23 16:52:27 +01001881
1882 if (!capable(CAP_NET_ADMIN))
1883 return -EPERM;
1884
1885 if (CHECK_ATTR(BPF_PROG_DETACH))
1886 return -EINVAL;
1887
1888 switch (attr->attach_type) {
1889 case BPF_CGROUP_INET_INGRESS:
1890 case BPF_CGROUP_INET_EGRESS:
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07001891 ptype = BPF_PROG_TYPE_CGROUP_SKB;
1892 break;
David Ahern610236582016-12-01 08:48:04 -08001893 case BPF_CGROUP_INET_SOCK_CREATE:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001894 case BPF_CGROUP_INET4_POST_BIND:
1895 case BPF_CGROUP_INET6_POST_BIND:
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07001896 ptype = BPF_PROG_TYPE_CGROUP_SOCK;
1897 break;
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001898 case BPF_CGROUP_INET4_BIND:
1899 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07001900 case BPF_CGROUP_INET4_CONNECT:
1901 case BPF_CGROUP_INET6_CONNECT:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07001902 case BPF_CGROUP_UDP4_SENDMSG:
1903 case BPF_CGROUP_UDP6_SENDMSG:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001904 ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
1905 break;
Lawrence Brakmo40304b22017-06-30 20:02:40 -07001906 case BPF_CGROUP_SOCK_OPS:
Alexei Starovoitov324bda9e62017-10-02 22:50:21 -07001907 ptype = BPF_PROG_TYPE_SOCK_OPS;
Daniel Mackf4324552016-11-23 16:52:27 +01001908 break;
Roman Gushchinebc614f2017-11-05 08:15:32 -05001909 case BPF_CGROUP_DEVICE:
1910 ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
1911 break;
John Fastabend4f738ad2018-03-18 12:57:10 -07001912 case BPF_SK_MSG_VERDICT:
Daniel Borkmann604326b2018-10-13 02:45:58 +02001913 return sock_map_get_from_fd(attr, NULL);
John Fastabend5a67da22017-09-08 14:00:49 -07001914 case BPF_SK_SKB_STREAM_PARSER:
1915 case BPF_SK_SKB_STREAM_VERDICT:
Daniel Borkmann604326b2018-10-13 02:45:58 +02001916 return sock_map_get_from_fd(attr, NULL);
Sean Youngf4364dc2018-05-27 12:24:09 +01001917 case BPF_LIRC_MODE2:
1918 return lirc_prog_detach(attr);
Petar Penkovd58e4682018-09-14 07:46:18 -07001919 case BPF_FLOW_DISSECTOR:
1920 return skb_flow_dissector_bpf_prog_detach(attr);
Daniel Mackf4324552016-11-23 16:52:27 +01001921 default:
1922 return -EINVAL;
1923 }
1924
Sean Youngfdb5c452018-06-19 00:04:24 +01001925 return cgroup_bpf_prog_detach(attr, ptype);
Daniel Mackf4324552016-11-23 16:52:27 +01001926}
Lawrence Brakmo40304b22017-06-30 20:02:40 -07001927
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07001928#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
1929
1930static int bpf_prog_query(const union bpf_attr *attr,
1931 union bpf_attr __user *uattr)
1932{
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07001933 if (!capable(CAP_NET_ADMIN))
1934 return -EPERM;
1935 if (CHECK_ATTR(BPF_PROG_QUERY))
1936 return -EINVAL;
1937 if (attr->query.query_flags & ~BPF_F_QUERY_EFFECTIVE)
1938 return -EINVAL;
1939
1940 switch (attr->query.attach_type) {
1941 case BPF_CGROUP_INET_INGRESS:
1942 case BPF_CGROUP_INET_EGRESS:
1943 case BPF_CGROUP_INET_SOCK_CREATE:
Andrey Ignatov4fbac772018-03-30 15:08:02 -07001944 case BPF_CGROUP_INET4_BIND:
1945 case BPF_CGROUP_INET6_BIND:
Andrey Ignatovaac3fc32018-03-30 15:08:07 -07001946 case BPF_CGROUP_INET4_POST_BIND:
1947 case BPF_CGROUP_INET6_POST_BIND:
Andrey Ignatovd74bad42018-03-30 15:08:05 -07001948 case BPF_CGROUP_INET4_CONNECT:
1949 case BPF_CGROUP_INET6_CONNECT:
Andrey Ignatov1cedee12018-05-25 08:55:23 -07001950 case BPF_CGROUP_UDP4_SENDMSG:
1951 case BPF_CGROUP_UDP6_SENDMSG:
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07001952 case BPF_CGROUP_SOCK_OPS:
Roman Gushchinebc614f2017-11-05 08:15:32 -05001953 case BPF_CGROUP_DEVICE:
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07001954 break;
Sean Youngf4364dc2018-05-27 12:24:09 +01001955 case BPF_LIRC_MODE2:
1956 return lirc_prog_query(attr, uattr);
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07001957 default:
1958 return -EINVAL;
1959 }
Sean Youngfdb5c452018-06-19 00:04:24 +01001960
1961 return cgroup_bpf_prog_query(attr, uattr);
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07001962}
Daniel Mackf4324552016-11-23 16:52:27 +01001963
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07001964#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration
1965
1966static int bpf_prog_test_run(const union bpf_attr *attr,
1967 union bpf_attr __user *uattr)
1968{
1969 struct bpf_prog *prog;
1970 int ret = -ENOTSUPP;
1971
Alexei Starovoitov61f3c962018-01-17 16:52:02 -08001972 if (!capable(CAP_SYS_ADMIN))
1973 return -EPERM;
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07001974 if (CHECK_ATTR(BPF_PROG_TEST_RUN))
1975 return -EINVAL;
1976
1977 prog = bpf_prog_get(attr->test.prog_fd);
1978 if (IS_ERR(prog))
1979 return PTR_ERR(prog);
1980
1981 if (prog->aux->ops->test_run)
1982 ret = prog->aux->ops->test_run(prog, attr, uattr);
1983
1984 bpf_prog_put(prog);
1985 return ret;
1986}
1987
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07001988#define BPF_OBJ_GET_NEXT_ID_LAST_FIELD next_id
1989
1990static int bpf_obj_get_next_id(const union bpf_attr *attr,
1991 union bpf_attr __user *uattr,
1992 struct idr *idr,
1993 spinlock_t *lock)
1994{
1995 u32 next_id = attr->start_id;
1996 int err = 0;
1997
1998 if (CHECK_ATTR(BPF_OBJ_GET_NEXT_ID) || next_id >= INT_MAX)
1999 return -EINVAL;
2000
2001 if (!capable(CAP_SYS_ADMIN))
2002 return -EPERM;
2003
2004 next_id++;
2005 spin_lock_bh(lock);
2006 if (!idr_get_next(idr, &next_id))
2007 err = -ENOENT;
2008 spin_unlock_bh(lock);
2009
2010 if (!err)
2011 err = put_user(next_id, &uattr->next_id);
2012
2013 return err;
2014}
2015
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07002016#define BPF_PROG_GET_FD_BY_ID_LAST_FIELD prog_id
2017
2018static int bpf_prog_get_fd_by_id(const union bpf_attr *attr)
2019{
2020 struct bpf_prog *prog;
2021 u32 id = attr->prog_id;
2022 int fd;
2023
2024 if (CHECK_ATTR(BPF_PROG_GET_FD_BY_ID))
2025 return -EINVAL;
2026
2027 if (!capable(CAP_SYS_ADMIN))
2028 return -EPERM;
2029
2030 spin_lock_bh(&prog_idr_lock);
2031 prog = idr_find(&prog_idr, id);
2032 if (prog)
2033 prog = bpf_prog_inc_not_zero(prog);
2034 else
2035 prog = ERR_PTR(-ENOENT);
2036 spin_unlock_bh(&prog_idr_lock);
2037
2038 if (IS_ERR(prog))
2039 return PTR_ERR(prog);
2040
2041 fd = bpf_prog_new_fd(prog);
2042 if (fd < 0)
2043 bpf_prog_put(prog);
2044
2045 return fd;
2046}
2047
Chenbo Feng6e71b042017-10-18 13:00:22 -07002048#define BPF_MAP_GET_FD_BY_ID_LAST_FIELD open_flags
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002049
2050static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
2051{
2052 struct bpf_map *map;
2053 u32 id = attr->map_id;
Chenbo Feng6e71b042017-10-18 13:00:22 -07002054 int f_flags;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002055 int fd;
2056
Chenbo Feng6e71b042017-10-18 13:00:22 -07002057 if (CHECK_ATTR(BPF_MAP_GET_FD_BY_ID) ||
2058 attr->open_flags & ~BPF_OBJ_FLAG_MASK)
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002059 return -EINVAL;
2060
2061 if (!capable(CAP_SYS_ADMIN))
2062 return -EPERM;
2063
Chenbo Feng6e71b042017-10-18 13:00:22 -07002064 f_flags = bpf_get_file_flag(attr->open_flags);
2065 if (f_flags < 0)
2066 return f_flags;
2067
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002068 spin_lock_bh(&map_idr_lock);
2069 map = idr_find(&map_idr, id);
2070 if (map)
2071 map = bpf_map_inc_not_zero(map, true);
2072 else
2073 map = ERR_PTR(-ENOENT);
2074 spin_unlock_bh(&map_idr_lock);
2075
2076 if (IS_ERR(map))
2077 return PTR_ERR(map);
2078
Chenbo Feng6e71b042017-10-18 13:00:22 -07002079 fd = bpf_map_new_fd(map, f_flags);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002080 if (fd < 0)
Peng Sun781e6282019-02-26 22:15:37 +08002081 bpf_map_put_with_uref(map);
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002082
2083 return fd;
2084}
2085
Daniel Borkmann7105e822017-12-20 13:42:57 +01002086static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002087 unsigned long addr, u32 *off,
2088 u32 *type)
Daniel Borkmann7105e822017-12-20 13:42:57 +01002089{
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002090 const struct bpf_map *map;
Daniel Borkmann7105e822017-12-20 13:42:57 +01002091 int i;
2092
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002093 for (i = 0, *off = 0; i < prog->aux->used_map_cnt; i++) {
2094 map = prog->aux->used_maps[i];
2095 if (map == (void *)addr) {
2096 *type = BPF_PSEUDO_MAP_FD;
2097 return map;
2098 }
2099 if (!map->ops->map_direct_value_meta)
2100 continue;
2101 if (!map->ops->map_direct_value_meta(map, addr, off)) {
2102 *type = BPF_PSEUDO_MAP_VALUE;
2103 return map;
2104 }
2105 }
2106
Daniel Borkmann7105e822017-12-20 13:42:57 +01002107 return NULL;
2108}
2109
2110static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
2111{
2112 const struct bpf_map *map;
2113 struct bpf_insn *insns;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002114 u32 off, type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01002115 u64 imm;
2116 int i;
2117
2118 insns = kmemdup(prog->insnsi, bpf_prog_insn_size(prog),
2119 GFP_USER);
2120 if (!insns)
2121 return insns;
2122
2123 for (i = 0; i < prog->len; i++) {
2124 if (insns[i].code == (BPF_JMP | BPF_TAIL_CALL)) {
2125 insns[i].code = BPF_JMP | BPF_CALL;
2126 insns[i].imm = BPF_FUNC_tail_call;
2127 /* fall-through */
2128 }
2129 if (insns[i].code == (BPF_JMP | BPF_CALL) ||
2130 insns[i].code == (BPF_JMP | BPF_CALL_ARGS)) {
2131 if (insns[i].code == (BPF_JMP | BPF_CALL_ARGS))
2132 insns[i].code = BPF_JMP | BPF_CALL;
2133 if (!bpf_dump_raw_ok())
2134 insns[i].imm = 0;
2135 continue;
2136 }
2137
2138 if (insns[i].code != (BPF_LD | BPF_IMM | BPF_DW))
2139 continue;
2140
2141 imm = ((u64)insns[i + 1].imm << 32) | (u32)insns[i].imm;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002142 map = bpf_map_from_imm(prog, imm, &off, &type);
Daniel Borkmann7105e822017-12-20 13:42:57 +01002143 if (map) {
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002144 insns[i].src_reg = type;
Daniel Borkmann7105e822017-12-20 13:42:57 +01002145 insns[i].imm = map->id;
Daniel Borkmannd8eca5b2019-04-09 23:20:03 +02002146 insns[i + 1].imm = off;
Daniel Borkmann7105e822017-12-20 13:42:57 +01002147 continue;
2148 }
Daniel Borkmann7105e822017-12-20 13:42:57 +01002149 }
2150
2151 return insns;
2152}
2153
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002154static int set_info_rec_size(struct bpf_prog_info *info)
2155{
2156 /*
2157 * Ensure info.*_rec_size is the same as kernel expected size
2158 *
2159 * or
2160 *
2161 * Only allow zero *_rec_size if both _rec_size and _cnt are
2162 * zero. In this case, the kernel will set the expected
2163 * _rec_size back to the info.
2164 */
2165
Yonghong Song11d8b822018-12-10 14:14:08 -08002166 if ((info->nr_func_info || info->func_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002167 info->func_info_rec_size != sizeof(struct bpf_func_info))
2168 return -EINVAL;
2169
Yonghong Song11d8b822018-12-10 14:14:08 -08002170 if ((info->nr_line_info || info->line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002171 info->line_info_rec_size != sizeof(struct bpf_line_info))
2172 return -EINVAL;
2173
Yonghong Song11d8b822018-12-10 14:14:08 -08002174 if ((info->nr_jited_line_info || info->jited_line_info_rec_size) &&
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002175 info->jited_line_info_rec_size != sizeof(__u64))
2176 return -EINVAL;
2177
2178 info->func_info_rec_size = sizeof(struct bpf_func_info);
2179 info->line_info_rec_size = sizeof(struct bpf_line_info);
2180 info->jited_line_info_rec_size = sizeof(__u64);
2181
2182 return 0;
2183}
2184
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002185static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
2186 const union bpf_attr *attr,
2187 union bpf_attr __user *uattr)
2188{
2189 struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
2190 struct bpf_prog_info info = {};
2191 u32 info_len = attr->info.info_len;
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08002192 struct bpf_prog_stats stats;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002193 char __user *uinsns;
2194 u32 ulen;
2195 int err;
2196
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07002197 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002198 if (err)
2199 return err;
2200 info_len = min_t(u32, sizeof(info), info_len);
2201
2202 if (copy_from_user(&info, uinfo, info_len))
Daniel Borkmann89b09682017-07-27 21:02:46 +02002203 return -EFAULT;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002204
2205 info.type = prog->type;
2206 info.id = prog->aux->id;
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07002207 info.load_time = prog->aux->load_time;
2208 info.created_by_uid = from_kuid_munged(current_user_ns(),
2209 prog->aux->user->uid);
Jiri Olsab85fab02018-04-25 19:41:06 +02002210 info.gpl_compatible = prog->gpl_compatible;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002211
2212 memcpy(info.tag, prog->tag, sizeof(prog->tag));
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07002213 memcpy(info.name, prog->aux->name, sizeof(prog->aux->name));
2214
2215 ulen = info.nr_map_ids;
2216 info.nr_map_ids = prog->aux->used_map_cnt;
2217 ulen = min_t(u32, info.nr_map_ids, ulen);
2218 if (ulen) {
Martin KaFai Lau721e08d2017-09-29 10:52:17 -07002219 u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
Martin KaFai Laucb4d2b32017-09-27 14:37:52 -07002220 u32 i;
2221
2222 for (i = 0; i < ulen; i++)
2223 if (put_user(prog->aux->used_maps[i]->id,
2224 &user_map_ids[i]))
2225 return -EFAULT;
2226 }
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002227
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002228 err = set_info_rec_size(&info);
2229 if (err)
2230 return err;
Martin KaFai Lau73372242018-12-05 17:35:43 -08002231
Alexei Starovoitov5f8f8b92019-02-25 14:28:40 -08002232 bpf_prog_get_stats(prog, &stats);
2233 info.run_time_ns = stats.nsecs;
2234 info.run_cnt = stats.cnt;
2235
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002236 if (!capable(CAP_SYS_ADMIN)) {
2237 info.jited_prog_len = 0;
2238 info.xlated_prog_len = 0;
Sandipan Dasdbecd732018-05-24 12:26:48 +05302239 info.nr_jited_ksyms = 0;
Daniel Borkmann28c2fae2018-11-02 11:35:46 +01002240 info.nr_jited_func_lens = 0;
Yonghong Song11d8b822018-12-10 14:14:08 -08002241 info.nr_func_info = 0;
2242 info.nr_line_info = 0;
2243 info.nr_jited_line_info = 0;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002244 goto done;
2245 }
2246
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002247 ulen = info.xlated_prog_len;
Daniel Borkmann9975a542017-07-28 17:05:25 +02002248 info.xlated_prog_len = bpf_prog_insn_size(prog);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002249 if (info.xlated_prog_len && ulen) {
Daniel Borkmann7105e822017-12-20 13:42:57 +01002250 struct bpf_insn *insns_sanitized;
2251 bool fault;
2252
2253 if (prog->blinded && !bpf_dump_raw_ok()) {
2254 info.xlated_prog_insns = 0;
2255 goto done;
2256 }
2257 insns_sanitized = bpf_insn_prepare_dump(prog);
2258 if (!insns_sanitized)
2259 return -ENOMEM;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002260 uinsns = u64_to_user_ptr(info.xlated_prog_insns);
2261 ulen = min_t(u32, info.xlated_prog_len, ulen);
Daniel Borkmann7105e822017-12-20 13:42:57 +01002262 fault = copy_to_user(uinsns, insns_sanitized, ulen);
2263 kfree(insns_sanitized);
2264 if (fault)
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002265 return -EFAULT;
2266 }
2267
Jakub Kicinski675fc272017-12-27 18:39:09 -08002268 if (bpf_prog_is_dev_bound(prog->aux)) {
2269 err = bpf_prog_offload_info_fill(&info, prog);
2270 if (err)
2271 return err;
Jiong Wangfcfb1262018-01-16 16:05:19 -08002272 goto done;
2273 }
2274
2275 /* NOTE: the following code is supposed to be skipped for offload.
2276 * bpf_prog_offload_info_fill() is the place to fill similar fields
2277 * for offload.
2278 */
2279 ulen = info.jited_prog_len;
Sandipan Das4d56a762018-05-24 12:26:51 +05302280 if (prog->aux->func_cnt) {
2281 u32 i;
2282
2283 info.jited_prog_len = 0;
2284 for (i = 0; i < prog->aux->func_cnt; i++)
2285 info.jited_prog_len += prog->aux->func[i]->jited_len;
2286 } else {
2287 info.jited_prog_len = prog->jited_len;
2288 }
2289
Jiong Wangfcfb1262018-01-16 16:05:19 -08002290 if (info.jited_prog_len && ulen) {
2291 if (bpf_dump_raw_ok()) {
2292 uinsns = u64_to_user_ptr(info.jited_prog_insns);
2293 ulen = min_t(u32, info.jited_prog_len, ulen);
Sandipan Das4d56a762018-05-24 12:26:51 +05302294
2295 /* for multi-function programs, copy the JITed
2296 * instructions for all the functions
2297 */
2298 if (prog->aux->func_cnt) {
2299 u32 len, free, i;
2300 u8 *img;
2301
2302 free = ulen;
2303 for (i = 0; i < prog->aux->func_cnt; i++) {
2304 len = prog->aux->func[i]->jited_len;
2305 len = min_t(u32, len, free);
2306 img = (u8 *) prog->aux->func[i]->bpf_func;
2307 if (copy_to_user(uinsns, img, len))
2308 return -EFAULT;
2309 uinsns += len;
2310 free -= len;
2311 if (!free)
2312 break;
2313 }
2314 } else {
2315 if (copy_to_user(uinsns, prog->bpf_func, ulen))
2316 return -EFAULT;
2317 }
Jiong Wangfcfb1262018-01-16 16:05:19 -08002318 } else {
2319 info.jited_prog_insns = 0;
2320 }
Jakub Kicinski675fc272017-12-27 18:39:09 -08002321 }
2322
Sandipan Dasdbecd732018-05-24 12:26:48 +05302323 ulen = info.nr_jited_ksyms;
Song Liuff1889f2018-11-02 10:16:17 -07002324 info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08002325 if (ulen) {
Sandipan Dasdbecd732018-05-24 12:26:48 +05302326 if (bpf_dump_raw_ok()) {
Song Liuff1889f2018-11-02 10:16:17 -07002327 unsigned long ksym_addr;
Sandipan Dasdbecd732018-05-24 12:26:48 +05302328 u64 __user *user_ksyms;
Sandipan Dasdbecd732018-05-24 12:26:48 +05302329 u32 i;
2330
2331 /* copy the address of the kernel symbol
2332 * corresponding to each function
2333 */
2334 ulen = min_t(u32, info.nr_jited_ksyms, ulen);
2335 user_ksyms = u64_to_user_ptr(info.jited_ksyms);
Song Liuff1889f2018-11-02 10:16:17 -07002336 if (prog->aux->func_cnt) {
2337 for (i = 0; i < ulen; i++) {
2338 ksym_addr = (unsigned long)
2339 prog->aux->func[i]->bpf_func;
2340 if (put_user((u64) ksym_addr,
2341 &user_ksyms[i]))
2342 return -EFAULT;
2343 }
2344 } else {
2345 ksym_addr = (unsigned long) prog->bpf_func;
2346 if (put_user((u64) ksym_addr, &user_ksyms[0]))
Sandipan Dasdbecd732018-05-24 12:26:48 +05302347 return -EFAULT;
2348 }
2349 } else {
2350 info.jited_ksyms = 0;
2351 }
2352 }
2353
Sandipan Das815581c2018-05-24 12:26:52 +05302354 ulen = info.nr_jited_func_lens;
Song Liuff1889f2018-11-02 10:16:17 -07002355 info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
Song Liu7a5725d2018-12-10 11:17:50 -08002356 if (ulen) {
Sandipan Das815581c2018-05-24 12:26:52 +05302357 if (bpf_dump_raw_ok()) {
2358 u32 __user *user_lens;
2359 u32 func_len, i;
2360
2361 /* copy the JITed image lengths for each function */
2362 ulen = min_t(u32, info.nr_jited_func_lens, ulen);
2363 user_lens = u64_to_user_ptr(info.jited_func_lens);
Song Liuff1889f2018-11-02 10:16:17 -07002364 if (prog->aux->func_cnt) {
2365 for (i = 0; i < ulen; i++) {
2366 func_len =
2367 prog->aux->func[i]->jited_len;
2368 if (put_user(func_len, &user_lens[i]))
2369 return -EFAULT;
2370 }
2371 } else {
2372 func_len = prog->jited_len;
2373 if (put_user(func_len, &user_lens[0]))
Sandipan Das815581c2018-05-24 12:26:52 +05302374 return -EFAULT;
2375 }
2376 } else {
2377 info.jited_func_lens = 0;
2378 }
2379 }
2380
Martin KaFai Lau73372242018-12-05 17:35:43 -08002381 if (prog->aux->btf)
Yonghong Song838e9692018-11-19 15:29:11 -08002382 info.btf_id = btf_id(prog->aux->btf);
2383
Yonghong Song11d8b822018-12-10 14:14:08 -08002384 ulen = info.nr_func_info;
2385 info.nr_func_info = prog->aux->func_info_cnt;
2386 if (info.nr_func_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08002387 char __user *user_finfo;
Yonghong Song838e9692018-11-19 15:29:11 -08002388
Martin KaFai Lau9e794162018-12-12 10:18:21 -08002389 user_finfo = u64_to_user_ptr(info.func_info);
2390 ulen = min_t(u32, info.nr_func_info, ulen);
2391 if (copy_to_user(user_finfo, prog->aux->func_info,
2392 info.func_info_rec_size * ulen))
2393 return -EFAULT;
Yonghong Song838e9692018-11-19 15:29:11 -08002394 }
2395
Yonghong Song11d8b822018-12-10 14:14:08 -08002396 ulen = info.nr_line_info;
2397 info.nr_line_info = prog->aux->nr_linfo;
2398 if (info.nr_line_info && ulen) {
Martin KaFai Lau9e794162018-12-12 10:18:21 -08002399 __u8 __user *user_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002400
Martin KaFai Lau9e794162018-12-12 10:18:21 -08002401 user_linfo = u64_to_user_ptr(info.line_info);
2402 ulen = min_t(u32, info.nr_line_info, ulen);
2403 if (copy_to_user(user_linfo, prog->aux->linfo,
2404 info.line_info_rec_size * ulen))
2405 return -EFAULT;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002406 }
2407
Yonghong Song11d8b822018-12-10 14:14:08 -08002408 ulen = info.nr_jited_line_info;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002409 if (prog->aux->jited_linfo)
Yonghong Song11d8b822018-12-10 14:14:08 -08002410 info.nr_jited_line_info = prog->aux->nr_linfo;
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002411 else
Yonghong Song11d8b822018-12-10 14:14:08 -08002412 info.nr_jited_line_info = 0;
2413 if (info.nr_jited_line_info && ulen) {
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002414 if (bpf_dump_raw_ok()) {
2415 __u64 __user *user_linfo;
2416 u32 i;
2417
2418 user_linfo = u64_to_user_ptr(info.jited_line_info);
Yonghong Song11d8b822018-12-10 14:14:08 -08002419 ulen = min_t(u32, info.nr_jited_line_info, ulen);
Martin KaFai Lauc454a462018-12-07 16:42:25 -08002420 for (i = 0; i < ulen; i++) {
2421 if (put_user((__u64)(long)prog->aux->jited_linfo[i],
2422 &user_linfo[i]))
2423 return -EFAULT;
2424 }
2425 } else {
2426 info.jited_line_info = 0;
2427 }
2428 }
2429
Song Liuc872bdb2018-12-12 09:37:46 -08002430 ulen = info.nr_prog_tags;
2431 info.nr_prog_tags = prog->aux->func_cnt ? : 1;
2432 if (ulen) {
2433 __u8 __user (*user_prog_tags)[BPF_TAG_SIZE];
2434 u32 i;
2435
2436 user_prog_tags = u64_to_user_ptr(info.prog_tags);
2437 ulen = min_t(u32, info.nr_prog_tags, ulen);
2438 if (prog->aux->func_cnt) {
2439 for (i = 0; i < ulen; i++) {
2440 if (copy_to_user(user_prog_tags[i],
2441 prog->aux->func[i]->tag,
2442 BPF_TAG_SIZE))
2443 return -EFAULT;
2444 }
2445 } else {
2446 if (copy_to_user(user_prog_tags[0],
2447 prog->tag, BPF_TAG_SIZE))
2448 return -EFAULT;
2449 }
2450 }
2451
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002452done:
2453 if (copy_to_user(uinfo, &info, info_len) ||
2454 put_user(info_len, &uattr->info.info_len))
2455 return -EFAULT;
2456
2457 return 0;
2458}
2459
2460static int bpf_map_get_info_by_fd(struct bpf_map *map,
2461 const union bpf_attr *attr,
2462 union bpf_attr __user *uattr)
2463{
2464 struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
2465 struct bpf_map_info info = {};
2466 u32 info_len = attr->info.info_len;
2467 int err;
2468
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07002469 err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002470 if (err)
2471 return err;
2472 info_len = min_t(u32, sizeof(info), info_len);
2473
2474 info.type = map->map_type;
2475 info.id = map->id;
2476 info.key_size = map->key_size;
2477 info.value_size = map->value_size;
2478 info.max_entries = map->max_entries;
2479 info.map_flags = map->map_flags;
Martin KaFai Lauad5b1772017-09-27 14:37:53 -07002480 memcpy(info.name, map->name, sizeof(map->name));
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002481
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07002482 if (map->btf) {
2483 info.btf_id = btf_id(map->btf);
Martin KaFai Lau9b2cf322018-05-22 14:57:21 -07002484 info.btf_key_type_id = map->btf_key_type_id;
2485 info.btf_value_type_id = map->btf_value_type_id;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07002486 }
2487
Jakub Kicinski52775b32018-01-17 19:13:28 -08002488 if (bpf_map_is_dev_bound(map)) {
2489 err = bpf_map_offload_info_fill(&info, map);
2490 if (err)
2491 return err;
2492 }
2493
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002494 if (copy_to_user(uinfo, &info, info_len) ||
2495 put_user(info_len, &uattr->info.info_len))
2496 return -EFAULT;
2497
2498 return 0;
2499}
2500
Martin KaFai Lau62dab842018-05-04 14:49:52 -07002501static int bpf_btf_get_info_by_fd(struct btf *btf,
2502 const union bpf_attr *attr,
2503 union bpf_attr __user *uattr)
2504{
2505 struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info);
2506 u32 info_len = attr->info.info_len;
2507 int err;
2508
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07002509 err = bpf_check_uarg_tail_zero(uinfo, sizeof(*uinfo), info_len);
Martin KaFai Lau62dab842018-05-04 14:49:52 -07002510 if (err)
2511 return err;
2512
2513 return btf_get_info_by_fd(btf, attr, uattr);
2514}
2515
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002516#define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info
2517
2518static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
2519 union bpf_attr __user *uattr)
2520{
2521 int ufd = attr->info.bpf_fd;
2522 struct fd f;
2523 int err;
2524
2525 if (CHECK_ATTR(BPF_OBJ_GET_INFO_BY_FD))
2526 return -EINVAL;
2527
2528 f = fdget(ufd);
2529 if (!f.file)
2530 return -EBADFD;
2531
2532 if (f.file->f_op == &bpf_prog_fops)
2533 err = bpf_prog_get_info_by_fd(f.file->private_data, attr,
2534 uattr);
2535 else if (f.file->f_op == &bpf_map_fops)
2536 err = bpf_map_get_info_by_fd(f.file->private_data, attr,
2537 uattr);
Martin KaFai Lau60197cf2018-04-18 15:56:02 -07002538 else if (f.file->f_op == &btf_fops)
Martin KaFai Lau62dab842018-05-04 14:49:52 -07002539 err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002540 else
2541 err = -EINVAL;
2542
2543 fdput(f);
2544 return err;
2545}
2546
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07002547#define BPF_BTF_LOAD_LAST_FIELD btf_log_level
2548
2549static int bpf_btf_load(const union bpf_attr *attr)
2550{
2551 if (CHECK_ATTR(BPF_BTF_LOAD))
2552 return -EINVAL;
2553
2554 if (!capable(CAP_SYS_ADMIN))
2555 return -EPERM;
2556
2557 return btf_new_fd(attr);
2558}
2559
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07002560#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id
2561
2562static int bpf_btf_get_fd_by_id(const union bpf_attr *attr)
2563{
2564 if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID))
2565 return -EINVAL;
2566
2567 if (!capable(CAP_SYS_ADMIN))
2568 return -EPERM;
2569
2570 return btf_get_fd_by_id(attr->btf_id);
2571}
2572
Yonghong Song41bdc4b2018-05-24 11:21:09 -07002573static int bpf_task_fd_query_copy(const union bpf_attr *attr,
2574 union bpf_attr __user *uattr,
2575 u32 prog_id, u32 fd_type,
2576 const char *buf, u64 probe_offset,
2577 u64 probe_addr)
2578{
2579 char __user *ubuf = u64_to_user_ptr(attr->task_fd_query.buf);
2580 u32 len = buf ? strlen(buf) : 0, input_len;
2581 int err = 0;
2582
2583 if (put_user(len, &uattr->task_fd_query.buf_len))
2584 return -EFAULT;
2585 input_len = attr->task_fd_query.buf_len;
2586 if (input_len && ubuf) {
2587 if (!len) {
2588 /* nothing to copy, just make ubuf NULL terminated */
2589 char zero = '\0';
2590
2591 if (put_user(zero, ubuf))
2592 return -EFAULT;
2593 } else if (input_len >= len + 1) {
2594 /* ubuf can hold the string with NULL terminator */
2595 if (copy_to_user(ubuf, buf, len + 1))
2596 return -EFAULT;
2597 } else {
2598 /* ubuf cannot hold the string with NULL terminator,
2599 * do a partial copy with NULL terminator.
2600 */
2601 char zero = '\0';
2602
2603 err = -ENOSPC;
2604 if (copy_to_user(ubuf, buf, input_len - 1))
2605 return -EFAULT;
2606 if (put_user(zero, ubuf + input_len - 1))
2607 return -EFAULT;
2608 }
2609 }
2610
2611 if (put_user(prog_id, &uattr->task_fd_query.prog_id) ||
2612 put_user(fd_type, &uattr->task_fd_query.fd_type) ||
2613 put_user(probe_offset, &uattr->task_fd_query.probe_offset) ||
2614 put_user(probe_addr, &uattr->task_fd_query.probe_addr))
2615 return -EFAULT;
2616
2617 return err;
2618}
2619
2620#define BPF_TASK_FD_QUERY_LAST_FIELD task_fd_query.probe_addr
2621
2622static int bpf_task_fd_query(const union bpf_attr *attr,
2623 union bpf_attr __user *uattr)
2624{
2625 pid_t pid = attr->task_fd_query.pid;
2626 u32 fd = attr->task_fd_query.fd;
2627 const struct perf_event *event;
2628 struct files_struct *files;
2629 struct task_struct *task;
2630 struct file *file;
2631 int err;
2632
2633 if (CHECK_ATTR(BPF_TASK_FD_QUERY))
2634 return -EINVAL;
2635
2636 if (!capable(CAP_SYS_ADMIN))
2637 return -EPERM;
2638
2639 if (attr->task_fd_query.flags != 0)
2640 return -EINVAL;
2641
2642 task = get_pid_task(find_vpid(pid), PIDTYPE_PID);
2643 if (!task)
2644 return -ENOENT;
2645
2646 files = get_files_struct(task);
2647 put_task_struct(task);
2648 if (!files)
2649 return -ENOENT;
2650
2651 err = 0;
2652 spin_lock(&files->file_lock);
2653 file = fcheck_files(files, fd);
2654 if (!file)
2655 err = -EBADF;
2656 else
2657 get_file(file);
2658 spin_unlock(&files->file_lock);
2659 put_files_struct(files);
2660
2661 if (err)
2662 goto out;
2663
2664 if (file->f_op == &bpf_raw_tp_fops) {
2665 struct bpf_raw_tracepoint *raw_tp = file->private_data;
2666 struct bpf_raw_event_map *btp = raw_tp->btp;
2667
2668 err = bpf_task_fd_query_copy(attr, uattr,
2669 raw_tp->prog->aux->id,
2670 BPF_FD_TYPE_RAW_TRACEPOINT,
2671 btp->tp->name, 0, 0);
2672 goto put_file;
2673 }
2674
2675 event = perf_get_event(file);
2676 if (!IS_ERR(event)) {
2677 u64 probe_offset, probe_addr;
2678 u32 prog_id, fd_type;
2679 const char *buf;
2680
2681 err = bpf_get_perf_event_info(event, &prog_id, &fd_type,
2682 &buf, &probe_offset,
2683 &probe_addr);
2684 if (!err)
2685 err = bpf_task_fd_query_copy(attr, uattr, prog_id,
2686 fd_type, buf,
2687 probe_offset,
2688 probe_addr);
2689 goto put_file;
2690 }
2691
2692 err = -ENOTSUPP;
2693put_file:
2694 fput(file);
2695out:
2696 return err;
2697}
2698
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07002699SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
2700{
2701 union bpf_attr attr = {};
2702 int err;
2703
Chenbo Feng0fa4fe82018-03-19 17:57:27 -07002704 if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN))
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07002705 return -EPERM;
2706
Martin KaFai Laudcab51f2018-05-22 15:03:31 -07002707 err = bpf_check_uarg_tail_zero(uattr, sizeof(attr), size);
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002708 if (err)
2709 return err;
2710 size = min_t(u32, size, sizeof(attr));
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07002711
2712 /* copy attributes from user space, may be less than sizeof(bpf_attr) */
2713 if (copy_from_user(&attr, uattr, size) != 0)
2714 return -EFAULT;
2715
Chenbo Fengafdb09c2017-10-18 13:00:24 -07002716 err = security_bpf(cmd, &attr, size);
2717 if (err < 0)
2718 return err;
2719
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07002720 switch (cmd) {
2721 case BPF_MAP_CREATE:
2722 err = map_create(&attr);
2723 break;
Alexei Starovoitovdb20fd22014-09-26 00:16:59 -07002724 case BPF_MAP_LOOKUP_ELEM:
2725 err = map_lookup_elem(&attr);
2726 break;
2727 case BPF_MAP_UPDATE_ELEM:
2728 err = map_update_elem(&attr);
2729 break;
2730 case BPF_MAP_DELETE_ELEM:
2731 err = map_delete_elem(&attr);
2732 break;
2733 case BPF_MAP_GET_NEXT_KEY:
2734 err = map_get_next_key(&attr);
2735 break;
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002736 case BPF_PROG_LOAD:
Yonghong Song838e9692018-11-19 15:29:11 -08002737 err = bpf_prog_load(&attr, uattr);
Alexei Starovoitov09756af2014-09-26 00:17:00 -07002738 break;
Daniel Borkmannb2197752015-10-29 14:58:09 +01002739 case BPF_OBJ_PIN:
2740 err = bpf_obj_pin(&attr);
2741 break;
2742 case BPF_OBJ_GET:
2743 err = bpf_obj_get(&attr);
2744 break;
Daniel Mackf4324552016-11-23 16:52:27 +01002745 case BPF_PROG_ATTACH:
2746 err = bpf_prog_attach(&attr);
2747 break;
2748 case BPF_PROG_DETACH:
2749 err = bpf_prog_detach(&attr);
2750 break;
Alexei Starovoitov468e2f62017-10-02 22:50:22 -07002751 case BPF_PROG_QUERY:
2752 err = bpf_prog_query(&attr, uattr);
2753 break;
Alexei Starovoitov1cf1cae2017-03-30 21:45:38 -07002754 case BPF_PROG_TEST_RUN:
2755 err = bpf_prog_test_run(&attr, uattr);
2756 break;
Martin KaFai Lau34ad5582017-06-05 12:15:48 -07002757 case BPF_PROG_GET_NEXT_ID:
2758 err = bpf_obj_get_next_id(&attr, uattr,
2759 &prog_idr, &prog_idr_lock);
2760 break;
2761 case BPF_MAP_GET_NEXT_ID:
2762 err = bpf_obj_get_next_id(&attr, uattr,
2763 &map_idr, &map_idr_lock);
2764 break;
Martin KaFai Laub16d9aa2017-06-05 12:15:49 -07002765 case BPF_PROG_GET_FD_BY_ID:
2766 err = bpf_prog_get_fd_by_id(&attr);
2767 break;
Martin KaFai Laubd5f5f4e2017-06-05 12:15:50 -07002768 case BPF_MAP_GET_FD_BY_ID:
2769 err = bpf_map_get_fd_by_id(&attr);
2770 break;
Martin KaFai Lau1e270972017-06-05 12:15:52 -07002771 case BPF_OBJ_GET_INFO_BY_FD:
2772 err = bpf_obj_get_info_by_fd(&attr, uattr);
2773 break;
Alexei Starovoitovc4f66992018-03-28 12:05:37 -07002774 case BPF_RAW_TRACEPOINT_OPEN:
2775 err = bpf_raw_tracepoint_open(&attr);
2776 break;
Martin KaFai Lauf56a6532018-04-18 15:56:01 -07002777 case BPF_BTF_LOAD:
2778 err = bpf_btf_load(&attr);
2779 break;
Martin KaFai Lau78958fc2018-05-04 14:49:51 -07002780 case BPF_BTF_GET_FD_BY_ID:
2781 err = bpf_btf_get_fd_by_id(&attr);
2782 break;
Yonghong Song41bdc4b2018-05-24 11:21:09 -07002783 case BPF_TASK_FD_QUERY:
2784 err = bpf_task_fd_query(&attr, uattr);
2785 break;
Mauricio Vasquez Bbd513cd2018-10-18 15:16:30 +02002786 case BPF_MAP_LOOKUP_AND_DELETE_ELEM:
2787 err = map_lookup_and_delete_elem(&attr);
2788 break;
Alexei Starovoitov99c55f72014-09-26 00:16:57 -07002789 default:
2790 err = -EINVAL;
2791 break;
2792 }
2793
2794 return err;
2795}