199c55f7dSAlexei Starovoitov /* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com 299c55f7dSAlexei Starovoitov * 399c55f7dSAlexei Starovoitov * This program is free software; you can redistribute it and/or 499c55f7dSAlexei Starovoitov * modify it under the terms of version 2 of the GNU General Public 599c55f7dSAlexei Starovoitov * License as published by the Free Software Foundation. 699c55f7dSAlexei Starovoitov * 799c55f7dSAlexei Starovoitov * This program is distributed in the hope that it will be useful, but 899c55f7dSAlexei Starovoitov * WITHOUT ANY WARRANTY; without even the implied warranty of 999c55f7dSAlexei Starovoitov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1099c55f7dSAlexei Starovoitov * General Public License for more details. 1199c55f7dSAlexei Starovoitov */ 1299c55f7dSAlexei Starovoitov #include <linux/bpf.h> 1399c55f7dSAlexei Starovoitov #include <linux/syscalls.h> 1499c55f7dSAlexei Starovoitov #include <linux/slab.h> 1599c55f7dSAlexei Starovoitov #include <linux/anon_inodes.h> 16db20fd2bSAlexei Starovoitov #include <linux/file.h> 1709756af4SAlexei Starovoitov #include <linux/license.h> 1809756af4SAlexei Starovoitov #include <linux/filter.h> 192541517cSAlexei Starovoitov #include <linux/version.h> 2099c55f7dSAlexei Starovoitov 21b121d1e7SAlexei Starovoitov DEFINE_PER_CPU(int, bpf_prog_active); 22b121d1e7SAlexei Starovoitov 231be7f75dSAlexei Starovoitov int sysctl_unprivileged_bpf_disabled __read_mostly; 241be7f75dSAlexei Starovoitov 2599c55f7dSAlexei Starovoitov static LIST_HEAD(bpf_map_types); 2699c55f7dSAlexei Starovoitov 2799c55f7dSAlexei Starovoitov static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) 2899c55f7dSAlexei Starovoitov { 2999c55f7dSAlexei Starovoitov struct bpf_map_type_list *tl; 3099c55f7dSAlexei Starovoitov struct bpf_map *map; 3199c55f7dSAlexei Starovoitov 3299c55f7dSAlexei Starovoitov list_for_each_entry(tl, &bpf_map_types, list_node) { 3399c55f7dSAlexei Starovoitov if (tl->type == attr->map_type) { 3499c55f7dSAlexei Starovoitov map = tl->ops->map_alloc(attr); 3599c55f7dSAlexei Starovoitov if (IS_ERR(map)) 3699c55f7dSAlexei Starovoitov return map; 3799c55f7dSAlexei Starovoitov map->ops = tl->ops; 3899c55f7dSAlexei Starovoitov map->map_type = attr->map_type; 3999c55f7dSAlexei Starovoitov return map; 4099c55f7dSAlexei Starovoitov } 4199c55f7dSAlexei Starovoitov } 4299c55f7dSAlexei Starovoitov return ERR_PTR(-EINVAL); 4399c55f7dSAlexei Starovoitov } 4499c55f7dSAlexei Starovoitov 4599c55f7dSAlexei Starovoitov /* boot time registration of different map implementations */ 4699c55f7dSAlexei Starovoitov void bpf_register_map_type(struct bpf_map_type_list *tl) 4799c55f7dSAlexei Starovoitov { 4899c55f7dSAlexei Starovoitov list_add(&tl->list_node, &bpf_map_types); 4999c55f7dSAlexei Starovoitov } 5099c55f7dSAlexei Starovoitov 516c905981SAlexei Starovoitov int bpf_map_precharge_memlock(u32 pages) 526c905981SAlexei Starovoitov { 536c905981SAlexei Starovoitov struct user_struct *user = get_current_user(); 546c905981SAlexei Starovoitov unsigned long memlock_limit, cur; 556c905981SAlexei Starovoitov 566c905981SAlexei Starovoitov memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 576c905981SAlexei Starovoitov cur = atomic_long_read(&user->locked_vm); 586c905981SAlexei Starovoitov free_uid(user); 596c905981SAlexei Starovoitov if (cur + pages > memlock_limit) 606c905981SAlexei Starovoitov return -EPERM; 616c905981SAlexei Starovoitov return 0; 626c905981SAlexei Starovoitov } 636c905981SAlexei Starovoitov 64aaac3ba9SAlexei Starovoitov static int bpf_map_charge_memlock(struct bpf_map *map) 65aaac3ba9SAlexei Starovoitov { 66aaac3ba9SAlexei Starovoitov struct user_struct *user = get_current_user(); 67aaac3ba9SAlexei Starovoitov unsigned long memlock_limit; 68aaac3ba9SAlexei Starovoitov 69aaac3ba9SAlexei Starovoitov memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 70aaac3ba9SAlexei Starovoitov 71aaac3ba9SAlexei Starovoitov atomic_long_add(map->pages, &user->locked_vm); 72aaac3ba9SAlexei Starovoitov 73aaac3ba9SAlexei Starovoitov if (atomic_long_read(&user->locked_vm) > memlock_limit) { 74aaac3ba9SAlexei Starovoitov atomic_long_sub(map->pages, &user->locked_vm); 75aaac3ba9SAlexei Starovoitov free_uid(user); 76aaac3ba9SAlexei Starovoitov return -EPERM; 77aaac3ba9SAlexei Starovoitov } 78aaac3ba9SAlexei Starovoitov map->user = user; 79aaac3ba9SAlexei Starovoitov return 0; 80aaac3ba9SAlexei Starovoitov } 81aaac3ba9SAlexei Starovoitov 82aaac3ba9SAlexei Starovoitov static void bpf_map_uncharge_memlock(struct bpf_map *map) 83aaac3ba9SAlexei Starovoitov { 84aaac3ba9SAlexei Starovoitov struct user_struct *user = map->user; 85aaac3ba9SAlexei Starovoitov 86aaac3ba9SAlexei Starovoitov atomic_long_sub(map->pages, &user->locked_vm); 87aaac3ba9SAlexei Starovoitov free_uid(user); 88aaac3ba9SAlexei Starovoitov } 89aaac3ba9SAlexei Starovoitov 9099c55f7dSAlexei Starovoitov /* called from workqueue */ 9199c55f7dSAlexei Starovoitov static void bpf_map_free_deferred(struct work_struct *work) 9299c55f7dSAlexei Starovoitov { 9399c55f7dSAlexei Starovoitov struct bpf_map *map = container_of(work, struct bpf_map, work); 9499c55f7dSAlexei Starovoitov 95aaac3ba9SAlexei Starovoitov bpf_map_uncharge_memlock(map); 9699c55f7dSAlexei Starovoitov /* implementation dependent freeing */ 9799c55f7dSAlexei Starovoitov map->ops->map_free(map); 9899c55f7dSAlexei Starovoitov } 9999c55f7dSAlexei Starovoitov 100c9da161cSDaniel Borkmann static void bpf_map_put_uref(struct bpf_map *map) 101c9da161cSDaniel Borkmann { 102c9da161cSDaniel Borkmann if (atomic_dec_and_test(&map->usercnt)) { 103c9da161cSDaniel Borkmann if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) 104c9da161cSDaniel Borkmann bpf_fd_array_map_clear(map); 105c9da161cSDaniel Borkmann } 106c9da161cSDaniel Borkmann } 107c9da161cSDaniel Borkmann 10899c55f7dSAlexei Starovoitov /* decrement map refcnt and schedule it for freeing via workqueue 10999c55f7dSAlexei Starovoitov * (unrelying map implementation ops->map_free() might sleep) 11099c55f7dSAlexei Starovoitov */ 11199c55f7dSAlexei Starovoitov void bpf_map_put(struct bpf_map *map) 11299c55f7dSAlexei Starovoitov { 11399c55f7dSAlexei Starovoitov if (atomic_dec_and_test(&map->refcnt)) { 11499c55f7dSAlexei Starovoitov INIT_WORK(&map->work, bpf_map_free_deferred); 11599c55f7dSAlexei Starovoitov schedule_work(&map->work); 11699c55f7dSAlexei Starovoitov } 11799c55f7dSAlexei Starovoitov } 11899c55f7dSAlexei Starovoitov 119c9da161cSDaniel Borkmann void bpf_map_put_with_uref(struct bpf_map *map) 120c9da161cSDaniel Borkmann { 121c9da161cSDaniel Borkmann bpf_map_put_uref(map); 122c9da161cSDaniel Borkmann bpf_map_put(map); 123c9da161cSDaniel Borkmann } 124c9da161cSDaniel Borkmann 12599c55f7dSAlexei Starovoitov static int bpf_map_release(struct inode *inode, struct file *filp) 12699c55f7dSAlexei Starovoitov { 127c9da161cSDaniel Borkmann bpf_map_put_with_uref(filp->private_data); 12899c55f7dSAlexei Starovoitov return 0; 12999c55f7dSAlexei Starovoitov } 13099c55f7dSAlexei Starovoitov 131f99bf205SDaniel Borkmann #ifdef CONFIG_PROC_FS 132f99bf205SDaniel Borkmann static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) 133f99bf205SDaniel Borkmann { 134f99bf205SDaniel Borkmann const struct bpf_map *map = filp->private_data; 135f99bf205SDaniel Borkmann 136f99bf205SDaniel Borkmann seq_printf(m, 137f99bf205SDaniel Borkmann "map_type:\t%u\n" 138f99bf205SDaniel Borkmann "key_size:\t%u\n" 139f99bf205SDaniel Borkmann "value_size:\t%u\n" 140f99bf205SDaniel Borkmann "max_entries:\t%u\n", 141f99bf205SDaniel Borkmann map->map_type, 142f99bf205SDaniel Borkmann map->key_size, 143f99bf205SDaniel Borkmann map->value_size, 144f99bf205SDaniel Borkmann map->max_entries); 145f99bf205SDaniel Borkmann } 146f99bf205SDaniel Borkmann #endif 147f99bf205SDaniel Borkmann 14899c55f7dSAlexei Starovoitov static const struct file_operations bpf_map_fops = { 149f99bf205SDaniel Borkmann #ifdef CONFIG_PROC_FS 150f99bf205SDaniel Borkmann .show_fdinfo = bpf_map_show_fdinfo, 151f99bf205SDaniel Borkmann #endif 15299c55f7dSAlexei Starovoitov .release = bpf_map_release, 15399c55f7dSAlexei Starovoitov }; 15499c55f7dSAlexei Starovoitov 155b2197755SDaniel Borkmann int bpf_map_new_fd(struct bpf_map *map) 156aa79781bSDaniel Borkmann { 157aa79781bSDaniel Borkmann return anon_inode_getfd("bpf-map", &bpf_map_fops, map, 158aa79781bSDaniel Borkmann O_RDWR | O_CLOEXEC); 159aa79781bSDaniel Borkmann } 160aa79781bSDaniel Borkmann 16199c55f7dSAlexei Starovoitov /* helper macro to check that unused fields 'union bpf_attr' are zero */ 16299c55f7dSAlexei Starovoitov #define CHECK_ATTR(CMD) \ 16399c55f7dSAlexei Starovoitov memchr_inv((void *) &attr->CMD##_LAST_FIELD + \ 16499c55f7dSAlexei Starovoitov sizeof(attr->CMD##_LAST_FIELD), 0, \ 16599c55f7dSAlexei Starovoitov sizeof(*attr) - \ 16699c55f7dSAlexei Starovoitov offsetof(union bpf_attr, CMD##_LAST_FIELD) - \ 16799c55f7dSAlexei Starovoitov sizeof(attr->CMD##_LAST_FIELD)) != NULL 16899c55f7dSAlexei Starovoitov 1696c905981SAlexei Starovoitov #define BPF_MAP_CREATE_LAST_FIELD map_flags 17099c55f7dSAlexei Starovoitov /* called via syscall */ 17199c55f7dSAlexei Starovoitov static int map_create(union bpf_attr *attr) 17299c55f7dSAlexei Starovoitov { 17399c55f7dSAlexei Starovoitov struct bpf_map *map; 17499c55f7dSAlexei Starovoitov int err; 17599c55f7dSAlexei Starovoitov 17699c55f7dSAlexei Starovoitov err = CHECK_ATTR(BPF_MAP_CREATE); 17799c55f7dSAlexei Starovoitov if (err) 17899c55f7dSAlexei Starovoitov return -EINVAL; 17999c55f7dSAlexei Starovoitov 18099c55f7dSAlexei Starovoitov /* find map type and init map: hashtable vs rbtree vs bloom vs ... */ 18199c55f7dSAlexei Starovoitov map = find_and_alloc_map(attr); 18299c55f7dSAlexei Starovoitov if (IS_ERR(map)) 18399c55f7dSAlexei Starovoitov return PTR_ERR(map); 18499c55f7dSAlexei Starovoitov 18599c55f7dSAlexei Starovoitov atomic_set(&map->refcnt, 1); 186c9da161cSDaniel Borkmann atomic_set(&map->usercnt, 1); 18799c55f7dSAlexei Starovoitov 188aaac3ba9SAlexei Starovoitov err = bpf_map_charge_memlock(map); 189aaac3ba9SAlexei Starovoitov if (err) 190aaac3ba9SAlexei Starovoitov goto free_map; 191aaac3ba9SAlexei Starovoitov 192aa79781bSDaniel Borkmann err = bpf_map_new_fd(map); 19399c55f7dSAlexei Starovoitov if (err < 0) 19499c55f7dSAlexei Starovoitov /* failed to allocate fd */ 19599c55f7dSAlexei Starovoitov goto free_map; 19699c55f7dSAlexei Starovoitov 19799c55f7dSAlexei Starovoitov return err; 19899c55f7dSAlexei Starovoitov 19999c55f7dSAlexei Starovoitov free_map: 20099c55f7dSAlexei Starovoitov map->ops->map_free(map); 20199c55f7dSAlexei Starovoitov return err; 20299c55f7dSAlexei Starovoitov } 20399c55f7dSAlexei Starovoitov 204db20fd2bSAlexei Starovoitov /* if error is returned, fd is released. 205db20fd2bSAlexei Starovoitov * On success caller should complete fd access with matching fdput() 206db20fd2bSAlexei Starovoitov */ 207c2101297SDaniel Borkmann struct bpf_map *__bpf_map_get(struct fd f) 208db20fd2bSAlexei Starovoitov { 209db20fd2bSAlexei Starovoitov if (!f.file) 210db20fd2bSAlexei Starovoitov return ERR_PTR(-EBADF); 211db20fd2bSAlexei Starovoitov if (f.file->f_op != &bpf_map_fops) { 212db20fd2bSAlexei Starovoitov fdput(f); 213db20fd2bSAlexei Starovoitov return ERR_PTR(-EINVAL); 214db20fd2bSAlexei Starovoitov } 215db20fd2bSAlexei Starovoitov 216c2101297SDaniel Borkmann return f.file->private_data; 217c2101297SDaniel Borkmann } 218c2101297SDaniel Borkmann 219c9da161cSDaniel Borkmann void bpf_map_inc(struct bpf_map *map, bool uref) 220c9da161cSDaniel Borkmann { 221c9da161cSDaniel Borkmann atomic_inc(&map->refcnt); 222c9da161cSDaniel Borkmann if (uref) 223c9da161cSDaniel Borkmann atomic_inc(&map->usercnt); 224c9da161cSDaniel Borkmann } 225c9da161cSDaniel Borkmann 226c9da161cSDaniel Borkmann struct bpf_map *bpf_map_get_with_uref(u32 ufd) 227c2101297SDaniel Borkmann { 228c2101297SDaniel Borkmann struct fd f = fdget(ufd); 229c2101297SDaniel Borkmann struct bpf_map *map; 230c2101297SDaniel Borkmann 231c2101297SDaniel Borkmann map = __bpf_map_get(f); 232c2101297SDaniel Borkmann if (IS_ERR(map)) 233c2101297SDaniel Borkmann return map; 234c2101297SDaniel Borkmann 235c9da161cSDaniel Borkmann bpf_map_inc(map, true); 236c2101297SDaniel Borkmann fdput(f); 237db20fd2bSAlexei Starovoitov 238db20fd2bSAlexei Starovoitov return map; 239db20fd2bSAlexei Starovoitov } 240db20fd2bSAlexei Starovoitov 241db20fd2bSAlexei Starovoitov /* helper to convert user pointers passed inside __aligned_u64 fields */ 242db20fd2bSAlexei Starovoitov static void __user *u64_to_ptr(__u64 val) 243db20fd2bSAlexei Starovoitov { 244db20fd2bSAlexei Starovoitov return (void __user *) (unsigned long) val; 245db20fd2bSAlexei Starovoitov } 246db20fd2bSAlexei Starovoitov 247db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */ 248db20fd2bSAlexei Starovoitov #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value 249db20fd2bSAlexei Starovoitov 250db20fd2bSAlexei Starovoitov static int map_lookup_elem(union bpf_attr *attr) 251db20fd2bSAlexei Starovoitov { 252db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 253db20fd2bSAlexei Starovoitov void __user *uvalue = u64_to_ptr(attr->value); 254db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 255db20fd2bSAlexei Starovoitov struct bpf_map *map; 2568ebe667cSAlexei Starovoitov void *key, *value, *ptr; 25715a07b33SAlexei Starovoitov u32 value_size; 258592867bfSDaniel Borkmann struct fd f; 259db20fd2bSAlexei Starovoitov int err; 260db20fd2bSAlexei Starovoitov 261db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) 262db20fd2bSAlexei Starovoitov return -EINVAL; 263db20fd2bSAlexei Starovoitov 264592867bfSDaniel Borkmann f = fdget(ufd); 265c2101297SDaniel Borkmann map = __bpf_map_get(f); 266db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 267db20fd2bSAlexei Starovoitov return PTR_ERR(map); 268db20fd2bSAlexei Starovoitov 269db20fd2bSAlexei Starovoitov err = -ENOMEM; 270db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 271db20fd2bSAlexei Starovoitov if (!key) 272db20fd2bSAlexei Starovoitov goto err_put; 273db20fd2bSAlexei Starovoitov 274db20fd2bSAlexei Starovoitov err = -EFAULT; 275db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 276db20fd2bSAlexei Starovoitov goto free_key; 277db20fd2bSAlexei Starovoitov 27815a07b33SAlexei Starovoitov if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || 27915a07b33SAlexei Starovoitov map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) 28015a07b33SAlexei Starovoitov value_size = round_up(map->value_size, 8) * num_possible_cpus(); 28115a07b33SAlexei Starovoitov else 28215a07b33SAlexei Starovoitov value_size = map->value_size; 28315a07b33SAlexei Starovoitov 2848ebe667cSAlexei Starovoitov err = -ENOMEM; 28515a07b33SAlexei Starovoitov value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); 286db20fd2bSAlexei Starovoitov if (!value) 2878ebe667cSAlexei Starovoitov goto free_key; 2888ebe667cSAlexei Starovoitov 28915a07b33SAlexei Starovoitov if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) { 29015a07b33SAlexei Starovoitov err = bpf_percpu_hash_copy(map, key, value); 29115a07b33SAlexei Starovoitov } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { 29215a07b33SAlexei Starovoitov err = bpf_percpu_array_copy(map, key, value); 293*557c0c6eSAlexei Starovoitov } else if (map->map_type == BPF_MAP_TYPE_STACK_TRACE) { 294*557c0c6eSAlexei Starovoitov err = bpf_stackmap_copy(map, key, value); 29515a07b33SAlexei Starovoitov } else { 2968ebe667cSAlexei Starovoitov rcu_read_lock(); 2978ebe667cSAlexei Starovoitov ptr = map->ops->map_lookup_elem(map, key); 2988ebe667cSAlexei Starovoitov if (ptr) 29915a07b33SAlexei Starovoitov memcpy(value, ptr, value_size); 3008ebe667cSAlexei Starovoitov rcu_read_unlock(); 30115a07b33SAlexei Starovoitov err = ptr ? 0 : -ENOENT; 30215a07b33SAlexei Starovoitov } 3038ebe667cSAlexei Starovoitov 30415a07b33SAlexei Starovoitov if (err) 3058ebe667cSAlexei Starovoitov goto free_value; 306db20fd2bSAlexei Starovoitov 307db20fd2bSAlexei Starovoitov err = -EFAULT; 30815a07b33SAlexei Starovoitov if (copy_to_user(uvalue, value, value_size) != 0) 3098ebe667cSAlexei Starovoitov goto free_value; 310db20fd2bSAlexei Starovoitov 311db20fd2bSAlexei Starovoitov err = 0; 312db20fd2bSAlexei Starovoitov 3138ebe667cSAlexei Starovoitov free_value: 3148ebe667cSAlexei Starovoitov kfree(value); 315db20fd2bSAlexei Starovoitov free_key: 316db20fd2bSAlexei Starovoitov kfree(key); 317db20fd2bSAlexei Starovoitov err_put: 318db20fd2bSAlexei Starovoitov fdput(f); 319db20fd2bSAlexei Starovoitov return err; 320db20fd2bSAlexei Starovoitov } 321db20fd2bSAlexei Starovoitov 3223274f520SAlexei Starovoitov #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags 323db20fd2bSAlexei Starovoitov 324db20fd2bSAlexei Starovoitov static int map_update_elem(union bpf_attr *attr) 325db20fd2bSAlexei Starovoitov { 326db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 327db20fd2bSAlexei Starovoitov void __user *uvalue = u64_to_ptr(attr->value); 328db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 329db20fd2bSAlexei Starovoitov struct bpf_map *map; 330db20fd2bSAlexei Starovoitov void *key, *value; 33115a07b33SAlexei Starovoitov u32 value_size; 332592867bfSDaniel Borkmann struct fd f; 333db20fd2bSAlexei Starovoitov int err; 334db20fd2bSAlexei Starovoitov 335db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM)) 336db20fd2bSAlexei Starovoitov return -EINVAL; 337db20fd2bSAlexei Starovoitov 338592867bfSDaniel Borkmann f = fdget(ufd); 339c2101297SDaniel Borkmann map = __bpf_map_get(f); 340db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 341db20fd2bSAlexei Starovoitov return PTR_ERR(map); 342db20fd2bSAlexei Starovoitov 343db20fd2bSAlexei Starovoitov err = -ENOMEM; 344db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 345db20fd2bSAlexei Starovoitov if (!key) 346db20fd2bSAlexei Starovoitov goto err_put; 347db20fd2bSAlexei Starovoitov 348db20fd2bSAlexei Starovoitov err = -EFAULT; 349db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 350db20fd2bSAlexei Starovoitov goto free_key; 351db20fd2bSAlexei Starovoitov 35215a07b33SAlexei Starovoitov if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || 35315a07b33SAlexei Starovoitov map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) 35415a07b33SAlexei Starovoitov value_size = round_up(map->value_size, 8) * num_possible_cpus(); 35515a07b33SAlexei Starovoitov else 35615a07b33SAlexei Starovoitov value_size = map->value_size; 35715a07b33SAlexei Starovoitov 358db20fd2bSAlexei Starovoitov err = -ENOMEM; 35915a07b33SAlexei Starovoitov value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); 360db20fd2bSAlexei Starovoitov if (!value) 361db20fd2bSAlexei Starovoitov goto free_key; 362db20fd2bSAlexei Starovoitov 363db20fd2bSAlexei Starovoitov err = -EFAULT; 36415a07b33SAlexei Starovoitov if (copy_from_user(value, uvalue, value_size) != 0) 365db20fd2bSAlexei Starovoitov goto free_value; 366db20fd2bSAlexei Starovoitov 367b121d1e7SAlexei Starovoitov /* must increment bpf_prog_active to avoid kprobe+bpf triggering from 368b121d1e7SAlexei Starovoitov * inside bpf map update or delete otherwise deadlocks are possible 369b121d1e7SAlexei Starovoitov */ 370b121d1e7SAlexei Starovoitov preempt_disable(); 371b121d1e7SAlexei Starovoitov __this_cpu_inc(bpf_prog_active); 37215a07b33SAlexei Starovoitov if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) { 37315a07b33SAlexei Starovoitov err = bpf_percpu_hash_update(map, key, value, attr->flags); 37415a07b33SAlexei Starovoitov } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { 37515a07b33SAlexei Starovoitov err = bpf_percpu_array_update(map, key, value, attr->flags); 37615a07b33SAlexei Starovoitov } else { 377db20fd2bSAlexei Starovoitov rcu_read_lock(); 3783274f520SAlexei Starovoitov err = map->ops->map_update_elem(map, key, value, attr->flags); 379db20fd2bSAlexei Starovoitov rcu_read_unlock(); 38015a07b33SAlexei Starovoitov } 381b121d1e7SAlexei Starovoitov __this_cpu_dec(bpf_prog_active); 382b121d1e7SAlexei Starovoitov preempt_enable(); 383db20fd2bSAlexei Starovoitov 384db20fd2bSAlexei Starovoitov free_value: 385db20fd2bSAlexei Starovoitov kfree(value); 386db20fd2bSAlexei Starovoitov free_key: 387db20fd2bSAlexei Starovoitov kfree(key); 388db20fd2bSAlexei Starovoitov err_put: 389db20fd2bSAlexei Starovoitov fdput(f); 390db20fd2bSAlexei Starovoitov return err; 391db20fd2bSAlexei Starovoitov } 392db20fd2bSAlexei Starovoitov 393db20fd2bSAlexei Starovoitov #define BPF_MAP_DELETE_ELEM_LAST_FIELD key 394db20fd2bSAlexei Starovoitov 395db20fd2bSAlexei Starovoitov static int map_delete_elem(union bpf_attr *attr) 396db20fd2bSAlexei Starovoitov { 397db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 398db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 399db20fd2bSAlexei Starovoitov struct bpf_map *map; 400592867bfSDaniel Borkmann struct fd f; 401db20fd2bSAlexei Starovoitov void *key; 402db20fd2bSAlexei Starovoitov int err; 403db20fd2bSAlexei Starovoitov 404db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_DELETE_ELEM)) 405db20fd2bSAlexei Starovoitov return -EINVAL; 406db20fd2bSAlexei Starovoitov 407592867bfSDaniel Borkmann f = fdget(ufd); 408c2101297SDaniel Borkmann map = __bpf_map_get(f); 409db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 410db20fd2bSAlexei Starovoitov return PTR_ERR(map); 411db20fd2bSAlexei Starovoitov 412db20fd2bSAlexei Starovoitov err = -ENOMEM; 413db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 414db20fd2bSAlexei Starovoitov if (!key) 415db20fd2bSAlexei Starovoitov goto err_put; 416db20fd2bSAlexei Starovoitov 417db20fd2bSAlexei Starovoitov err = -EFAULT; 418db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 419db20fd2bSAlexei Starovoitov goto free_key; 420db20fd2bSAlexei Starovoitov 421b121d1e7SAlexei Starovoitov preempt_disable(); 422b121d1e7SAlexei Starovoitov __this_cpu_inc(bpf_prog_active); 423db20fd2bSAlexei Starovoitov rcu_read_lock(); 424db20fd2bSAlexei Starovoitov err = map->ops->map_delete_elem(map, key); 425db20fd2bSAlexei Starovoitov rcu_read_unlock(); 426b121d1e7SAlexei Starovoitov __this_cpu_dec(bpf_prog_active); 427b121d1e7SAlexei Starovoitov preempt_enable(); 428db20fd2bSAlexei Starovoitov 429db20fd2bSAlexei Starovoitov free_key: 430db20fd2bSAlexei Starovoitov kfree(key); 431db20fd2bSAlexei Starovoitov err_put: 432db20fd2bSAlexei Starovoitov fdput(f); 433db20fd2bSAlexei Starovoitov return err; 434db20fd2bSAlexei Starovoitov } 435db20fd2bSAlexei Starovoitov 436db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */ 437db20fd2bSAlexei Starovoitov #define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key 438db20fd2bSAlexei Starovoitov 439db20fd2bSAlexei Starovoitov static int map_get_next_key(union bpf_attr *attr) 440db20fd2bSAlexei Starovoitov { 441db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 442db20fd2bSAlexei Starovoitov void __user *unext_key = u64_to_ptr(attr->next_key); 443db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 444db20fd2bSAlexei Starovoitov struct bpf_map *map; 445db20fd2bSAlexei Starovoitov void *key, *next_key; 446592867bfSDaniel Borkmann struct fd f; 447db20fd2bSAlexei Starovoitov int err; 448db20fd2bSAlexei Starovoitov 449db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY)) 450db20fd2bSAlexei Starovoitov return -EINVAL; 451db20fd2bSAlexei Starovoitov 452592867bfSDaniel Borkmann f = fdget(ufd); 453c2101297SDaniel Borkmann map = __bpf_map_get(f); 454db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 455db20fd2bSAlexei Starovoitov return PTR_ERR(map); 456db20fd2bSAlexei Starovoitov 457db20fd2bSAlexei Starovoitov err = -ENOMEM; 458db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 459db20fd2bSAlexei Starovoitov if (!key) 460db20fd2bSAlexei Starovoitov goto err_put; 461db20fd2bSAlexei Starovoitov 462db20fd2bSAlexei Starovoitov err = -EFAULT; 463db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 464db20fd2bSAlexei Starovoitov goto free_key; 465db20fd2bSAlexei Starovoitov 466db20fd2bSAlexei Starovoitov err = -ENOMEM; 467db20fd2bSAlexei Starovoitov next_key = kmalloc(map->key_size, GFP_USER); 468db20fd2bSAlexei Starovoitov if (!next_key) 469db20fd2bSAlexei Starovoitov goto free_key; 470db20fd2bSAlexei Starovoitov 471db20fd2bSAlexei Starovoitov rcu_read_lock(); 472db20fd2bSAlexei Starovoitov err = map->ops->map_get_next_key(map, key, next_key); 473db20fd2bSAlexei Starovoitov rcu_read_unlock(); 474db20fd2bSAlexei Starovoitov if (err) 475db20fd2bSAlexei Starovoitov goto free_next_key; 476db20fd2bSAlexei Starovoitov 477db20fd2bSAlexei Starovoitov err = -EFAULT; 478db20fd2bSAlexei Starovoitov if (copy_to_user(unext_key, next_key, map->key_size) != 0) 479db20fd2bSAlexei Starovoitov goto free_next_key; 480db20fd2bSAlexei Starovoitov 481db20fd2bSAlexei Starovoitov err = 0; 482db20fd2bSAlexei Starovoitov 483db20fd2bSAlexei Starovoitov free_next_key: 484db20fd2bSAlexei Starovoitov kfree(next_key); 485db20fd2bSAlexei Starovoitov free_key: 486db20fd2bSAlexei Starovoitov kfree(key); 487db20fd2bSAlexei Starovoitov err_put: 488db20fd2bSAlexei Starovoitov fdput(f); 489db20fd2bSAlexei Starovoitov return err; 490db20fd2bSAlexei Starovoitov } 491db20fd2bSAlexei Starovoitov 49209756af4SAlexei Starovoitov static LIST_HEAD(bpf_prog_types); 49309756af4SAlexei Starovoitov 49409756af4SAlexei Starovoitov static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog) 49509756af4SAlexei Starovoitov { 49609756af4SAlexei Starovoitov struct bpf_prog_type_list *tl; 49709756af4SAlexei Starovoitov 49809756af4SAlexei Starovoitov list_for_each_entry(tl, &bpf_prog_types, list_node) { 49909756af4SAlexei Starovoitov if (tl->type == type) { 50009756af4SAlexei Starovoitov prog->aux->ops = tl->ops; 50124701eceSDaniel Borkmann prog->type = type; 50209756af4SAlexei Starovoitov return 0; 50309756af4SAlexei Starovoitov } 50409756af4SAlexei Starovoitov } 50524701eceSDaniel Borkmann 50609756af4SAlexei Starovoitov return -EINVAL; 50709756af4SAlexei Starovoitov } 50809756af4SAlexei Starovoitov 50909756af4SAlexei Starovoitov void bpf_register_prog_type(struct bpf_prog_type_list *tl) 51009756af4SAlexei Starovoitov { 51109756af4SAlexei Starovoitov list_add(&tl->list_node, &bpf_prog_types); 51209756af4SAlexei Starovoitov } 51309756af4SAlexei Starovoitov 5140a542a86SAlexei Starovoitov /* fixup insn->imm field of bpf_call instructions: 5150a542a86SAlexei Starovoitov * if (insn->imm == BPF_FUNC_map_lookup_elem) 5160a542a86SAlexei Starovoitov * insn->imm = bpf_map_lookup_elem - __bpf_call_base; 5170a542a86SAlexei Starovoitov * else if (insn->imm == BPF_FUNC_map_update_elem) 5180a542a86SAlexei Starovoitov * insn->imm = bpf_map_update_elem - __bpf_call_base; 5190a542a86SAlexei Starovoitov * else ... 5200a542a86SAlexei Starovoitov * 5210a542a86SAlexei Starovoitov * this function is called after eBPF program passed verification 5220a542a86SAlexei Starovoitov */ 5230a542a86SAlexei Starovoitov static void fixup_bpf_calls(struct bpf_prog *prog) 5240a542a86SAlexei Starovoitov { 5250a542a86SAlexei Starovoitov const struct bpf_func_proto *fn; 5260a542a86SAlexei Starovoitov int i; 5270a542a86SAlexei Starovoitov 5280a542a86SAlexei Starovoitov for (i = 0; i < prog->len; i++) { 5290a542a86SAlexei Starovoitov struct bpf_insn *insn = &prog->insnsi[i]; 5300a542a86SAlexei Starovoitov 5310a542a86SAlexei Starovoitov if (insn->code == (BPF_JMP | BPF_CALL)) { 5320a542a86SAlexei Starovoitov /* we reach here when program has bpf_call instructions 5330a542a86SAlexei Starovoitov * and it passed bpf_check(), means that 5340a542a86SAlexei Starovoitov * ops->get_func_proto must have been supplied, check it 5350a542a86SAlexei Starovoitov */ 5360a542a86SAlexei Starovoitov BUG_ON(!prog->aux->ops->get_func_proto); 5370a542a86SAlexei Starovoitov 538c46646d0SDaniel Borkmann if (insn->imm == BPF_FUNC_get_route_realm) 539c46646d0SDaniel Borkmann prog->dst_needed = 1; 5403ad00405SDaniel Borkmann if (insn->imm == BPF_FUNC_get_prandom_u32) 5413ad00405SDaniel Borkmann bpf_user_rnd_init_once(); 54204fd61abSAlexei Starovoitov if (insn->imm == BPF_FUNC_tail_call) { 54304fd61abSAlexei Starovoitov /* mark bpf_tail_call as different opcode 54404fd61abSAlexei Starovoitov * to avoid conditional branch in 54504fd61abSAlexei Starovoitov * interpeter for every normal call 54604fd61abSAlexei Starovoitov * and to prevent accidental JITing by 54704fd61abSAlexei Starovoitov * JIT compiler that doesn't support 54804fd61abSAlexei Starovoitov * bpf_tail_call yet 54904fd61abSAlexei Starovoitov */ 55004fd61abSAlexei Starovoitov insn->imm = 0; 55104fd61abSAlexei Starovoitov insn->code |= BPF_X; 55204fd61abSAlexei Starovoitov continue; 55304fd61abSAlexei Starovoitov } 55404fd61abSAlexei Starovoitov 5550a542a86SAlexei Starovoitov fn = prog->aux->ops->get_func_proto(insn->imm); 5560a542a86SAlexei Starovoitov /* all functions that have prototype and verifier allowed 5570a542a86SAlexei Starovoitov * programs to call them, must be real in-kernel functions 5580a542a86SAlexei Starovoitov */ 5590a542a86SAlexei Starovoitov BUG_ON(!fn->func); 5600a542a86SAlexei Starovoitov insn->imm = fn->func - __bpf_call_base; 5610a542a86SAlexei Starovoitov } 5620a542a86SAlexei Starovoitov } 5630a542a86SAlexei Starovoitov } 5640a542a86SAlexei Starovoitov 56509756af4SAlexei Starovoitov /* drop refcnt on maps used by eBPF program and free auxilary data */ 56609756af4SAlexei Starovoitov static void free_used_maps(struct bpf_prog_aux *aux) 56709756af4SAlexei Starovoitov { 56809756af4SAlexei Starovoitov int i; 56909756af4SAlexei Starovoitov 57009756af4SAlexei Starovoitov for (i = 0; i < aux->used_map_cnt; i++) 57109756af4SAlexei Starovoitov bpf_map_put(aux->used_maps[i]); 57209756af4SAlexei Starovoitov 57309756af4SAlexei Starovoitov kfree(aux->used_maps); 57409756af4SAlexei Starovoitov } 57509756af4SAlexei Starovoitov 576aaac3ba9SAlexei Starovoitov static int bpf_prog_charge_memlock(struct bpf_prog *prog) 577aaac3ba9SAlexei Starovoitov { 578aaac3ba9SAlexei Starovoitov struct user_struct *user = get_current_user(); 579aaac3ba9SAlexei Starovoitov unsigned long memlock_limit; 580aaac3ba9SAlexei Starovoitov 581aaac3ba9SAlexei Starovoitov memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 582aaac3ba9SAlexei Starovoitov 583aaac3ba9SAlexei Starovoitov atomic_long_add(prog->pages, &user->locked_vm); 584aaac3ba9SAlexei Starovoitov if (atomic_long_read(&user->locked_vm) > memlock_limit) { 585aaac3ba9SAlexei Starovoitov atomic_long_sub(prog->pages, &user->locked_vm); 586aaac3ba9SAlexei Starovoitov free_uid(user); 587aaac3ba9SAlexei Starovoitov return -EPERM; 588aaac3ba9SAlexei Starovoitov } 589aaac3ba9SAlexei Starovoitov prog->aux->user = user; 590aaac3ba9SAlexei Starovoitov return 0; 591aaac3ba9SAlexei Starovoitov } 592aaac3ba9SAlexei Starovoitov 593aaac3ba9SAlexei Starovoitov static void bpf_prog_uncharge_memlock(struct bpf_prog *prog) 594aaac3ba9SAlexei Starovoitov { 595aaac3ba9SAlexei Starovoitov struct user_struct *user = prog->aux->user; 596aaac3ba9SAlexei Starovoitov 597aaac3ba9SAlexei Starovoitov atomic_long_sub(prog->pages, &user->locked_vm); 598aaac3ba9SAlexei Starovoitov free_uid(user); 599aaac3ba9SAlexei Starovoitov } 600aaac3ba9SAlexei Starovoitov 601e9d8afa9SDaniel Borkmann static void __prog_put_common(struct rcu_head *rcu) 602abf2e7d6SAlexei Starovoitov { 603abf2e7d6SAlexei Starovoitov struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu); 604abf2e7d6SAlexei Starovoitov 605abf2e7d6SAlexei Starovoitov free_used_maps(aux); 606aaac3ba9SAlexei Starovoitov bpf_prog_uncharge_memlock(aux->prog); 607abf2e7d6SAlexei Starovoitov bpf_prog_free(aux->prog); 608abf2e7d6SAlexei Starovoitov } 609abf2e7d6SAlexei Starovoitov 610abf2e7d6SAlexei Starovoitov /* version of bpf_prog_put() that is called after a grace period */ 611abf2e7d6SAlexei Starovoitov void bpf_prog_put_rcu(struct bpf_prog *prog) 612abf2e7d6SAlexei Starovoitov { 613e9d8afa9SDaniel Borkmann if (atomic_dec_and_test(&prog->aux->refcnt)) 614e9d8afa9SDaniel Borkmann call_rcu(&prog->aux->rcu, __prog_put_common); 615abf2e7d6SAlexei Starovoitov } 616abf2e7d6SAlexei Starovoitov 61709756af4SAlexei Starovoitov void bpf_prog_put(struct bpf_prog *prog) 61809756af4SAlexei Starovoitov { 619e9d8afa9SDaniel Borkmann if (atomic_dec_and_test(&prog->aux->refcnt)) 620e9d8afa9SDaniel Borkmann __prog_put_common(&prog->aux->rcu); 62109756af4SAlexei Starovoitov } 622e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_put); 62309756af4SAlexei Starovoitov 62409756af4SAlexei Starovoitov static int bpf_prog_release(struct inode *inode, struct file *filp) 62509756af4SAlexei Starovoitov { 62609756af4SAlexei Starovoitov struct bpf_prog *prog = filp->private_data; 62709756af4SAlexei Starovoitov 628abf2e7d6SAlexei Starovoitov bpf_prog_put_rcu(prog); 62909756af4SAlexei Starovoitov return 0; 63009756af4SAlexei Starovoitov } 63109756af4SAlexei Starovoitov 63209756af4SAlexei Starovoitov static const struct file_operations bpf_prog_fops = { 63309756af4SAlexei Starovoitov .release = bpf_prog_release, 63409756af4SAlexei Starovoitov }; 63509756af4SAlexei Starovoitov 636b2197755SDaniel Borkmann int bpf_prog_new_fd(struct bpf_prog *prog) 637aa79781bSDaniel Borkmann { 638aa79781bSDaniel Borkmann return anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog, 639aa79781bSDaniel Borkmann O_RDWR | O_CLOEXEC); 640aa79781bSDaniel Borkmann } 641aa79781bSDaniel Borkmann 642c2101297SDaniel Borkmann static struct bpf_prog *__bpf_prog_get(struct fd f) 64309756af4SAlexei Starovoitov { 64409756af4SAlexei Starovoitov if (!f.file) 64509756af4SAlexei Starovoitov return ERR_PTR(-EBADF); 64609756af4SAlexei Starovoitov if (f.file->f_op != &bpf_prog_fops) { 64709756af4SAlexei Starovoitov fdput(f); 64809756af4SAlexei Starovoitov return ERR_PTR(-EINVAL); 64909756af4SAlexei Starovoitov } 65009756af4SAlexei Starovoitov 651c2101297SDaniel Borkmann return f.file->private_data; 65209756af4SAlexei Starovoitov } 65309756af4SAlexei Starovoitov 65409756af4SAlexei Starovoitov /* called by sockets/tracing/seccomp before attaching program to an event 65509756af4SAlexei Starovoitov * pairs with bpf_prog_put() 65609756af4SAlexei Starovoitov */ 65709756af4SAlexei Starovoitov struct bpf_prog *bpf_prog_get(u32 ufd) 65809756af4SAlexei Starovoitov { 65909756af4SAlexei Starovoitov struct fd f = fdget(ufd); 66009756af4SAlexei Starovoitov struct bpf_prog *prog; 66109756af4SAlexei Starovoitov 662c2101297SDaniel Borkmann prog = __bpf_prog_get(f); 66309756af4SAlexei Starovoitov if (IS_ERR(prog)) 66409756af4SAlexei Starovoitov return prog; 66509756af4SAlexei Starovoitov 66609756af4SAlexei Starovoitov atomic_inc(&prog->aux->refcnt); 66709756af4SAlexei Starovoitov fdput(f); 668c2101297SDaniel Borkmann 66909756af4SAlexei Starovoitov return prog; 67009756af4SAlexei Starovoitov } 671e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_get); 67209756af4SAlexei Starovoitov 67309756af4SAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */ 6742541517cSAlexei Starovoitov #define BPF_PROG_LOAD_LAST_FIELD kern_version 67509756af4SAlexei Starovoitov 67609756af4SAlexei Starovoitov static int bpf_prog_load(union bpf_attr *attr) 67709756af4SAlexei Starovoitov { 67809756af4SAlexei Starovoitov enum bpf_prog_type type = attr->prog_type; 67909756af4SAlexei Starovoitov struct bpf_prog *prog; 68009756af4SAlexei Starovoitov int err; 68109756af4SAlexei Starovoitov char license[128]; 68209756af4SAlexei Starovoitov bool is_gpl; 68309756af4SAlexei Starovoitov 68409756af4SAlexei Starovoitov if (CHECK_ATTR(BPF_PROG_LOAD)) 68509756af4SAlexei Starovoitov return -EINVAL; 68609756af4SAlexei Starovoitov 68709756af4SAlexei Starovoitov /* copy eBPF program license from user space */ 68809756af4SAlexei Starovoitov if (strncpy_from_user(license, u64_to_ptr(attr->license), 68909756af4SAlexei Starovoitov sizeof(license) - 1) < 0) 69009756af4SAlexei Starovoitov return -EFAULT; 69109756af4SAlexei Starovoitov license[sizeof(license) - 1] = 0; 69209756af4SAlexei Starovoitov 69309756af4SAlexei Starovoitov /* eBPF programs must be GPL compatible to use GPL-ed functions */ 69409756af4SAlexei Starovoitov is_gpl = license_is_gpl_compatible(license); 69509756af4SAlexei Starovoitov 69609756af4SAlexei Starovoitov if (attr->insn_cnt >= BPF_MAXINSNS) 69709756af4SAlexei Starovoitov return -EINVAL; 69809756af4SAlexei Starovoitov 6992541517cSAlexei Starovoitov if (type == BPF_PROG_TYPE_KPROBE && 7002541517cSAlexei Starovoitov attr->kern_version != LINUX_VERSION_CODE) 7012541517cSAlexei Starovoitov return -EINVAL; 7022541517cSAlexei Starovoitov 7031be7f75dSAlexei Starovoitov if (type != BPF_PROG_TYPE_SOCKET_FILTER && !capable(CAP_SYS_ADMIN)) 7041be7f75dSAlexei Starovoitov return -EPERM; 7051be7f75dSAlexei Starovoitov 70609756af4SAlexei Starovoitov /* plain bpf_prog allocation */ 70709756af4SAlexei Starovoitov prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER); 70809756af4SAlexei Starovoitov if (!prog) 70909756af4SAlexei Starovoitov return -ENOMEM; 71009756af4SAlexei Starovoitov 711aaac3ba9SAlexei Starovoitov err = bpf_prog_charge_memlock(prog); 712aaac3ba9SAlexei Starovoitov if (err) 713aaac3ba9SAlexei Starovoitov goto free_prog_nouncharge; 714aaac3ba9SAlexei Starovoitov 71509756af4SAlexei Starovoitov prog->len = attr->insn_cnt; 71609756af4SAlexei Starovoitov 71709756af4SAlexei Starovoitov err = -EFAULT; 71809756af4SAlexei Starovoitov if (copy_from_user(prog->insns, u64_to_ptr(attr->insns), 71909756af4SAlexei Starovoitov prog->len * sizeof(struct bpf_insn)) != 0) 72009756af4SAlexei Starovoitov goto free_prog; 72109756af4SAlexei Starovoitov 72209756af4SAlexei Starovoitov prog->orig_prog = NULL; 723a91263d5SDaniel Borkmann prog->jited = 0; 72409756af4SAlexei Starovoitov 72509756af4SAlexei Starovoitov atomic_set(&prog->aux->refcnt, 1); 726a91263d5SDaniel Borkmann prog->gpl_compatible = is_gpl ? 1 : 0; 72709756af4SAlexei Starovoitov 72809756af4SAlexei Starovoitov /* find program type: socket_filter vs tracing_filter */ 72909756af4SAlexei Starovoitov err = find_prog_type(type, prog); 73009756af4SAlexei Starovoitov if (err < 0) 73109756af4SAlexei Starovoitov goto free_prog; 73209756af4SAlexei Starovoitov 73309756af4SAlexei Starovoitov /* run eBPF verifier */ 7349bac3d6dSAlexei Starovoitov err = bpf_check(&prog, attr); 73509756af4SAlexei Starovoitov if (err < 0) 73609756af4SAlexei Starovoitov goto free_used_maps; 73709756af4SAlexei Starovoitov 7380a542a86SAlexei Starovoitov /* fixup BPF_CALL->imm field */ 7390a542a86SAlexei Starovoitov fixup_bpf_calls(prog); 7400a542a86SAlexei Starovoitov 74109756af4SAlexei Starovoitov /* eBPF program is ready to be JITed */ 74204fd61abSAlexei Starovoitov err = bpf_prog_select_runtime(prog); 74304fd61abSAlexei Starovoitov if (err < 0) 74404fd61abSAlexei Starovoitov goto free_used_maps; 74509756af4SAlexei Starovoitov 746aa79781bSDaniel Borkmann err = bpf_prog_new_fd(prog); 74709756af4SAlexei Starovoitov if (err < 0) 74809756af4SAlexei Starovoitov /* failed to allocate fd */ 74909756af4SAlexei Starovoitov goto free_used_maps; 75009756af4SAlexei Starovoitov 75109756af4SAlexei Starovoitov return err; 75209756af4SAlexei Starovoitov 75309756af4SAlexei Starovoitov free_used_maps: 75409756af4SAlexei Starovoitov free_used_maps(prog->aux); 75509756af4SAlexei Starovoitov free_prog: 756aaac3ba9SAlexei Starovoitov bpf_prog_uncharge_memlock(prog); 757aaac3ba9SAlexei Starovoitov free_prog_nouncharge: 75809756af4SAlexei Starovoitov bpf_prog_free(prog); 75909756af4SAlexei Starovoitov return err; 76009756af4SAlexei Starovoitov } 76109756af4SAlexei Starovoitov 762b2197755SDaniel Borkmann #define BPF_OBJ_LAST_FIELD bpf_fd 763b2197755SDaniel Borkmann 764b2197755SDaniel Borkmann static int bpf_obj_pin(const union bpf_attr *attr) 765b2197755SDaniel Borkmann { 766b2197755SDaniel Borkmann if (CHECK_ATTR(BPF_OBJ)) 767b2197755SDaniel Borkmann return -EINVAL; 768b2197755SDaniel Borkmann 769b2197755SDaniel Borkmann return bpf_obj_pin_user(attr->bpf_fd, u64_to_ptr(attr->pathname)); 770b2197755SDaniel Borkmann } 771b2197755SDaniel Borkmann 772b2197755SDaniel Borkmann static int bpf_obj_get(const union bpf_attr *attr) 773b2197755SDaniel Borkmann { 774b2197755SDaniel Borkmann if (CHECK_ATTR(BPF_OBJ) || attr->bpf_fd != 0) 775b2197755SDaniel Borkmann return -EINVAL; 776b2197755SDaniel Borkmann 777b2197755SDaniel Borkmann return bpf_obj_get_user(u64_to_ptr(attr->pathname)); 778b2197755SDaniel Borkmann } 779b2197755SDaniel Borkmann 78099c55f7dSAlexei Starovoitov SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) 78199c55f7dSAlexei Starovoitov { 78299c55f7dSAlexei Starovoitov union bpf_attr attr = {}; 78399c55f7dSAlexei Starovoitov int err; 78499c55f7dSAlexei Starovoitov 7851be7f75dSAlexei Starovoitov if (!capable(CAP_SYS_ADMIN) && sysctl_unprivileged_bpf_disabled) 78699c55f7dSAlexei Starovoitov return -EPERM; 78799c55f7dSAlexei Starovoitov 78899c55f7dSAlexei Starovoitov if (!access_ok(VERIFY_READ, uattr, 1)) 78999c55f7dSAlexei Starovoitov return -EFAULT; 79099c55f7dSAlexei Starovoitov 79199c55f7dSAlexei Starovoitov if (size > PAGE_SIZE) /* silly large */ 79299c55f7dSAlexei Starovoitov return -E2BIG; 79399c55f7dSAlexei Starovoitov 79499c55f7dSAlexei Starovoitov /* If we're handed a bigger struct than we know of, 79599c55f7dSAlexei Starovoitov * ensure all the unknown bits are 0 - i.e. new 79699c55f7dSAlexei Starovoitov * user-space does not rely on any kernel feature 79799c55f7dSAlexei Starovoitov * extensions we dont know about yet. 79899c55f7dSAlexei Starovoitov */ 79999c55f7dSAlexei Starovoitov if (size > sizeof(attr)) { 80099c55f7dSAlexei Starovoitov unsigned char __user *addr; 80199c55f7dSAlexei Starovoitov unsigned char __user *end; 80299c55f7dSAlexei Starovoitov unsigned char val; 80399c55f7dSAlexei Starovoitov 80499c55f7dSAlexei Starovoitov addr = (void __user *)uattr + sizeof(attr); 80599c55f7dSAlexei Starovoitov end = (void __user *)uattr + size; 80699c55f7dSAlexei Starovoitov 80799c55f7dSAlexei Starovoitov for (; addr < end; addr++) { 80899c55f7dSAlexei Starovoitov err = get_user(val, addr); 80999c55f7dSAlexei Starovoitov if (err) 81099c55f7dSAlexei Starovoitov return err; 81199c55f7dSAlexei Starovoitov if (val) 81299c55f7dSAlexei Starovoitov return -E2BIG; 81399c55f7dSAlexei Starovoitov } 81499c55f7dSAlexei Starovoitov size = sizeof(attr); 81599c55f7dSAlexei Starovoitov } 81699c55f7dSAlexei Starovoitov 81799c55f7dSAlexei Starovoitov /* copy attributes from user space, may be less than sizeof(bpf_attr) */ 81899c55f7dSAlexei Starovoitov if (copy_from_user(&attr, uattr, size) != 0) 81999c55f7dSAlexei Starovoitov return -EFAULT; 82099c55f7dSAlexei Starovoitov 82199c55f7dSAlexei Starovoitov switch (cmd) { 82299c55f7dSAlexei Starovoitov case BPF_MAP_CREATE: 82399c55f7dSAlexei Starovoitov err = map_create(&attr); 82499c55f7dSAlexei Starovoitov break; 825db20fd2bSAlexei Starovoitov case BPF_MAP_LOOKUP_ELEM: 826db20fd2bSAlexei Starovoitov err = map_lookup_elem(&attr); 827db20fd2bSAlexei Starovoitov break; 828db20fd2bSAlexei Starovoitov case BPF_MAP_UPDATE_ELEM: 829db20fd2bSAlexei Starovoitov err = map_update_elem(&attr); 830db20fd2bSAlexei Starovoitov break; 831db20fd2bSAlexei Starovoitov case BPF_MAP_DELETE_ELEM: 832db20fd2bSAlexei Starovoitov err = map_delete_elem(&attr); 833db20fd2bSAlexei Starovoitov break; 834db20fd2bSAlexei Starovoitov case BPF_MAP_GET_NEXT_KEY: 835db20fd2bSAlexei Starovoitov err = map_get_next_key(&attr); 836db20fd2bSAlexei Starovoitov break; 83709756af4SAlexei Starovoitov case BPF_PROG_LOAD: 83809756af4SAlexei Starovoitov err = bpf_prog_load(&attr); 83909756af4SAlexei Starovoitov break; 840b2197755SDaniel Borkmann case BPF_OBJ_PIN: 841b2197755SDaniel Borkmann err = bpf_obj_pin(&attr); 842b2197755SDaniel Borkmann break; 843b2197755SDaniel Borkmann case BPF_OBJ_GET: 844b2197755SDaniel Borkmann err = bpf_obj_get(&attr); 845b2197755SDaniel Borkmann break; 84699c55f7dSAlexei Starovoitov default: 84799c55f7dSAlexei Starovoitov err = -EINVAL; 84899c55f7dSAlexei Starovoitov break; 84999c55f7dSAlexei Starovoitov } 85099c55f7dSAlexei Starovoitov 85199c55f7dSAlexei Starovoitov return err; 85299c55f7dSAlexei Starovoitov } 853