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 2199c55f7dSAlexei Starovoitov static LIST_HEAD(bpf_map_types); 2299c55f7dSAlexei Starovoitov 2399c55f7dSAlexei Starovoitov static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) 2499c55f7dSAlexei Starovoitov { 2599c55f7dSAlexei Starovoitov struct bpf_map_type_list *tl; 2699c55f7dSAlexei Starovoitov struct bpf_map *map; 2799c55f7dSAlexei Starovoitov 2899c55f7dSAlexei Starovoitov list_for_each_entry(tl, &bpf_map_types, list_node) { 2999c55f7dSAlexei Starovoitov if (tl->type == attr->map_type) { 3099c55f7dSAlexei Starovoitov map = tl->ops->map_alloc(attr); 3199c55f7dSAlexei Starovoitov if (IS_ERR(map)) 3299c55f7dSAlexei Starovoitov return map; 3399c55f7dSAlexei Starovoitov map->ops = tl->ops; 3499c55f7dSAlexei Starovoitov map->map_type = attr->map_type; 3599c55f7dSAlexei Starovoitov return map; 3699c55f7dSAlexei Starovoitov } 3799c55f7dSAlexei Starovoitov } 3899c55f7dSAlexei Starovoitov return ERR_PTR(-EINVAL); 3999c55f7dSAlexei Starovoitov } 4099c55f7dSAlexei Starovoitov 4199c55f7dSAlexei Starovoitov /* boot time registration of different map implementations */ 4299c55f7dSAlexei Starovoitov void bpf_register_map_type(struct bpf_map_type_list *tl) 4399c55f7dSAlexei Starovoitov { 4499c55f7dSAlexei Starovoitov list_add(&tl->list_node, &bpf_map_types); 4599c55f7dSAlexei Starovoitov } 4699c55f7dSAlexei Starovoitov 4799c55f7dSAlexei Starovoitov /* called from workqueue */ 4899c55f7dSAlexei Starovoitov static void bpf_map_free_deferred(struct work_struct *work) 4999c55f7dSAlexei Starovoitov { 5099c55f7dSAlexei Starovoitov struct bpf_map *map = container_of(work, struct bpf_map, work); 5199c55f7dSAlexei Starovoitov 5299c55f7dSAlexei Starovoitov /* implementation dependent freeing */ 5399c55f7dSAlexei Starovoitov map->ops->map_free(map); 5499c55f7dSAlexei Starovoitov } 5599c55f7dSAlexei Starovoitov 5699c55f7dSAlexei Starovoitov /* decrement map refcnt and schedule it for freeing via workqueue 5799c55f7dSAlexei Starovoitov * (unrelying map implementation ops->map_free() might sleep) 5899c55f7dSAlexei Starovoitov */ 5999c55f7dSAlexei Starovoitov void bpf_map_put(struct bpf_map *map) 6099c55f7dSAlexei Starovoitov { 6199c55f7dSAlexei Starovoitov if (atomic_dec_and_test(&map->refcnt)) { 6299c55f7dSAlexei Starovoitov INIT_WORK(&map->work, bpf_map_free_deferred); 6399c55f7dSAlexei Starovoitov schedule_work(&map->work); 6499c55f7dSAlexei Starovoitov } 6599c55f7dSAlexei Starovoitov } 6699c55f7dSAlexei Starovoitov 6799c55f7dSAlexei Starovoitov static int bpf_map_release(struct inode *inode, struct file *filp) 6899c55f7dSAlexei Starovoitov { 6999c55f7dSAlexei Starovoitov struct bpf_map *map = filp->private_data; 7099c55f7dSAlexei Starovoitov 7104fd61abSAlexei Starovoitov if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) 7204fd61abSAlexei Starovoitov /* prog_array stores refcnt-ed bpf_prog pointers 7304fd61abSAlexei Starovoitov * release them all when user space closes prog_array_fd 7404fd61abSAlexei Starovoitov */ 752a36f0b9SWang Nan bpf_fd_array_map_clear(map); 7604fd61abSAlexei Starovoitov 7799c55f7dSAlexei Starovoitov bpf_map_put(map); 7899c55f7dSAlexei Starovoitov return 0; 7999c55f7dSAlexei Starovoitov } 8099c55f7dSAlexei Starovoitov 8199c55f7dSAlexei Starovoitov static const struct file_operations bpf_map_fops = { 8299c55f7dSAlexei Starovoitov .release = bpf_map_release, 8399c55f7dSAlexei Starovoitov }; 8499c55f7dSAlexei Starovoitov 8599c55f7dSAlexei Starovoitov /* helper macro to check that unused fields 'union bpf_attr' are zero */ 8699c55f7dSAlexei Starovoitov #define CHECK_ATTR(CMD) \ 8799c55f7dSAlexei Starovoitov memchr_inv((void *) &attr->CMD##_LAST_FIELD + \ 8899c55f7dSAlexei Starovoitov sizeof(attr->CMD##_LAST_FIELD), 0, \ 8999c55f7dSAlexei Starovoitov sizeof(*attr) - \ 9099c55f7dSAlexei Starovoitov offsetof(union bpf_attr, CMD##_LAST_FIELD) - \ 9199c55f7dSAlexei Starovoitov sizeof(attr->CMD##_LAST_FIELD)) != NULL 9299c55f7dSAlexei Starovoitov 9399c55f7dSAlexei Starovoitov #define BPF_MAP_CREATE_LAST_FIELD max_entries 9499c55f7dSAlexei Starovoitov /* called via syscall */ 9599c55f7dSAlexei Starovoitov static int map_create(union bpf_attr *attr) 9699c55f7dSAlexei Starovoitov { 9799c55f7dSAlexei Starovoitov struct bpf_map *map; 9899c55f7dSAlexei Starovoitov int err; 9999c55f7dSAlexei Starovoitov 10099c55f7dSAlexei Starovoitov err = CHECK_ATTR(BPF_MAP_CREATE); 10199c55f7dSAlexei Starovoitov if (err) 10299c55f7dSAlexei Starovoitov return -EINVAL; 10399c55f7dSAlexei Starovoitov 10499c55f7dSAlexei Starovoitov /* find map type and init map: hashtable vs rbtree vs bloom vs ... */ 10599c55f7dSAlexei Starovoitov map = find_and_alloc_map(attr); 10699c55f7dSAlexei Starovoitov if (IS_ERR(map)) 10799c55f7dSAlexei Starovoitov return PTR_ERR(map); 10899c55f7dSAlexei Starovoitov 10999c55f7dSAlexei Starovoitov atomic_set(&map->refcnt, 1); 11099c55f7dSAlexei Starovoitov 11199c55f7dSAlexei Starovoitov err = anon_inode_getfd("bpf-map", &bpf_map_fops, map, O_RDWR | O_CLOEXEC); 11299c55f7dSAlexei Starovoitov 11399c55f7dSAlexei Starovoitov if (err < 0) 11499c55f7dSAlexei Starovoitov /* failed to allocate fd */ 11599c55f7dSAlexei Starovoitov goto free_map; 11699c55f7dSAlexei Starovoitov 11799c55f7dSAlexei Starovoitov return err; 11899c55f7dSAlexei Starovoitov 11999c55f7dSAlexei Starovoitov free_map: 12099c55f7dSAlexei Starovoitov map->ops->map_free(map); 12199c55f7dSAlexei Starovoitov return err; 12299c55f7dSAlexei Starovoitov } 12399c55f7dSAlexei Starovoitov 124db20fd2bSAlexei Starovoitov /* if error is returned, fd is released. 125db20fd2bSAlexei Starovoitov * On success caller should complete fd access with matching fdput() 126db20fd2bSAlexei Starovoitov */ 127db20fd2bSAlexei Starovoitov struct bpf_map *bpf_map_get(struct fd f) 128db20fd2bSAlexei Starovoitov { 129db20fd2bSAlexei Starovoitov struct bpf_map *map; 130db20fd2bSAlexei Starovoitov 131db20fd2bSAlexei Starovoitov if (!f.file) 132db20fd2bSAlexei Starovoitov return ERR_PTR(-EBADF); 133db20fd2bSAlexei Starovoitov 134db20fd2bSAlexei Starovoitov if (f.file->f_op != &bpf_map_fops) { 135db20fd2bSAlexei Starovoitov fdput(f); 136db20fd2bSAlexei Starovoitov return ERR_PTR(-EINVAL); 137db20fd2bSAlexei Starovoitov } 138db20fd2bSAlexei Starovoitov 139db20fd2bSAlexei Starovoitov map = f.file->private_data; 140db20fd2bSAlexei Starovoitov 141db20fd2bSAlexei Starovoitov return map; 142db20fd2bSAlexei Starovoitov } 143db20fd2bSAlexei Starovoitov 144db20fd2bSAlexei Starovoitov /* helper to convert user pointers passed inside __aligned_u64 fields */ 145db20fd2bSAlexei Starovoitov static void __user *u64_to_ptr(__u64 val) 146db20fd2bSAlexei Starovoitov { 147db20fd2bSAlexei Starovoitov return (void __user *) (unsigned long) val; 148db20fd2bSAlexei Starovoitov } 149db20fd2bSAlexei Starovoitov 150db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */ 151db20fd2bSAlexei Starovoitov #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value 152db20fd2bSAlexei Starovoitov 153db20fd2bSAlexei Starovoitov static int map_lookup_elem(union bpf_attr *attr) 154db20fd2bSAlexei Starovoitov { 155db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 156db20fd2bSAlexei Starovoitov void __user *uvalue = u64_to_ptr(attr->value); 157db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 158db20fd2bSAlexei Starovoitov struct bpf_map *map; 1598ebe667cSAlexei Starovoitov void *key, *value, *ptr; 160592867bfSDaniel Borkmann struct fd f; 161db20fd2bSAlexei Starovoitov int err; 162db20fd2bSAlexei Starovoitov 163db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) 164db20fd2bSAlexei Starovoitov return -EINVAL; 165db20fd2bSAlexei Starovoitov 166592867bfSDaniel Borkmann f = fdget(ufd); 167db20fd2bSAlexei Starovoitov map = bpf_map_get(f); 168db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 169db20fd2bSAlexei Starovoitov return PTR_ERR(map); 170db20fd2bSAlexei Starovoitov 171db20fd2bSAlexei Starovoitov err = -ENOMEM; 172db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 173db20fd2bSAlexei Starovoitov if (!key) 174db20fd2bSAlexei Starovoitov goto err_put; 175db20fd2bSAlexei Starovoitov 176db20fd2bSAlexei Starovoitov err = -EFAULT; 177db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 178db20fd2bSAlexei Starovoitov goto free_key; 179db20fd2bSAlexei Starovoitov 1808ebe667cSAlexei Starovoitov err = -ENOMEM; 1818ebe667cSAlexei Starovoitov value = kmalloc(map->value_size, GFP_USER); 182db20fd2bSAlexei Starovoitov if (!value) 1838ebe667cSAlexei Starovoitov goto free_key; 1848ebe667cSAlexei Starovoitov 1858ebe667cSAlexei Starovoitov rcu_read_lock(); 1868ebe667cSAlexei Starovoitov ptr = map->ops->map_lookup_elem(map, key); 1878ebe667cSAlexei Starovoitov if (ptr) 1888ebe667cSAlexei Starovoitov memcpy(value, ptr, map->value_size); 1898ebe667cSAlexei Starovoitov rcu_read_unlock(); 1908ebe667cSAlexei Starovoitov 1918ebe667cSAlexei Starovoitov err = -ENOENT; 1928ebe667cSAlexei Starovoitov if (!ptr) 1938ebe667cSAlexei Starovoitov goto free_value; 194db20fd2bSAlexei Starovoitov 195db20fd2bSAlexei Starovoitov err = -EFAULT; 196db20fd2bSAlexei Starovoitov if (copy_to_user(uvalue, value, map->value_size) != 0) 1978ebe667cSAlexei Starovoitov goto free_value; 198db20fd2bSAlexei Starovoitov 199db20fd2bSAlexei Starovoitov err = 0; 200db20fd2bSAlexei Starovoitov 2018ebe667cSAlexei Starovoitov free_value: 2028ebe667cSAlexei Starovoitov kfree(value); 203db20fd2bSAlexei Starovoitov free_key: 204db20fd2bSAlexei Starovoitov kfree(key); 205db20fd2bSAlexei Starovoitov err_put: 206db20fd2bSAlexei Starovoitov fdput(f); 207db20fd2bSAlexei Starovoitov return err; 208db20fd2bSAlexei Starovoitov } 209db20fd2bSAlexei Starovoitov 2103274f520SAlexei Starovoitov #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags 211db20fd2bSAlexei Starovoitov 212db20fd2bSAlexei Starovoitov static int map_update_elem(union bpf_attr *attr) 213db20fd2bSAlexei Starovoitov { 214db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 215db20fd2bSAlexei Starovoitov void __user *uvalue = u64_to_ptr(attr->value); 216db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 217db20fd2bSAlexei Starovoitov struct bpf_map *map; 218db20fd2bSAlexei Starovoitov void *key, *value; 219592867bfSDaniel Borkmann struct fd f; 220db20fd2bSAlexei Starovoitov int err; 221db20fd2bSAlexei Starovoitov 222db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_UPDATE_ELEM)) 223db20fd2bSAlexei Starovoitov return -EINVAL; 224db20fd2bSAlexei Starovoitov 225592867bfSDaniel Borkmann f = fdget(ufd); 226db20fd2bSAlexei Starovoitov map = bpf_map_get(f); 227db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 228db20fd2bSAlexei Starovoitov return PTR_ERR(map); 229db20fd2bSAlexei Starovoitov 230db20fd2bSAlexei Starovoitov err = -ENOMEM; 231db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 232db20fd2bSAlexei Starovoitov if (!key) 233db20fd2bSAlexei Starovoitov goto err_put; 234db20fd2bSAlexei Starovoitov 235db20fd2bSAlexei Starovoitov err = -EFAULT; 236db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 237db20fd2bSAlexei Starovoitov goto free_key; 238db20fd2bSAlexei Starovoitov 239db20fd2bSAlexei Starovoitov err = -ENOMEM; 240db20fd2bSAlexei Starovoitov value = kmalloc(map->value_size, GFP_USER); 241db20fd2bSAlexei Starovoitov if (!value) 242db20fd2bSAlexei Starovoitov goto free_key; 243db20fd2bSAlexei Starovoitov 244db20fd2bSAlexei Starovoitov err = -EFAULT; 245db20fd2bSAlexei Starovoitov if (copy_from_user(value, uvalue, map->value_size) != 0) 246db20fd2bSAlexei Starovoitov goto free_value; 247db20fd2bSAlexei Starovoitov 248db20fd2bSAlexei Starovoitov /* eBPF program that use maps are running under rcu_read_lock(), 249db20fd2bSAlexei Starovoitov * therefore all map accessors rely on this fact, so do the same here 250db20fd2bSAlexei Starovoitov */ 251db20fd2bSAlexei Starovoitov rcu_read_lock(); 2523274f520SAlexei Starovoitov err = map->ops->map_update_elem(map, key, value, attr->flags); 253db20fd2bSAlexei Starovoitov rcu_read_unlock(); 254db20fd2bSAlexei Starovoitov 255db20fd2bSAlexei Starovoitov free_value: 256db20fd2bSAlexei Starovoitov kfree(value); 257db20fd2bSAlexei Starovoitov free_key: 258db20fd2bSAlexei Starovoitov kfree(key); 259db20fd2bSAlexei Starovoitov err_put: 260db20fd2bSAlexei Starovoitov fdput(f); 261db20fd2bSAlexei Starovoitov return err; 262db20fd2bSAlexei Starovoitov } 263db20fd2bSAlexei Starovoitov 264db20fd2bSAlexei Starovoitov #define BPF_MAP_DELETE_ELEM_LAST_FIELD key 265db20fd2bSAlexei Starovoitov 266db20fd2bSAlexei Starovoitov static int map_delete_elem(union bpf_attr *attr) 267db20fd2bSAlexei Starovoitov { 268db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 269db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 270db20fd2bSAlexei Starovoitov struct bpf_map *map; 271592867bfSDaniel Borkmann struct fd f; 272db20fd2bSAlexei Starovoitov void *key; 273db20fd2bSAlexei Starovoitov int err; 274db20fd2bSAlexei Starovoitov 275db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_DELETE_ELEM)) 276db20fd2bSAlexei Starovoitov return -EINVAL; 277db20fd2bSAlexei Starovoitov 278592867bfSDaniel Borkmann f = fdget(ufd); 279db20fd2bSAlexei Starovoitov map = bpf_map_get(f); 280db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 281db20fd2bSAlexei Starovoitov return PTR_ERR(map); 282db20fd2bSAlexei Starovoitov 283db20fd2bSAlexei Starovoitov err = -ENOMEM; 284db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 285db20fd2bSAlexei Starovoitov if (!key) 286db20fd2bSAlexei Starovoitov goto err_put; 287db20fd2bSAlexei Starovoitov 288db20fd2bSAlexei Starovoitov err = -EFAULT; 289db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 290db20fd2bSAlexei Starovoitov goto free_key; 291db20fd2bSAlexei Starovoitov 292db20fd2bSAlexei Starovoitov rcu_read_lock(); 293db20fd2bSAlexei Starovoitov err = map->ops->map_delete_elem(map, key); 294db20fd2bSAlexei Starovoitov rcu_read_unlock(); 295db20fd2bSAlexei Starovoitov 296db20fd2bSAlexei Starovoitov free_key: 297db20fd2bSAlexei Starovoitov kfree(key); 298db20fd2bSAlexei Starovoitov err_put: 299db20fd2bSAlexei Starovoitov fdput(f); 300db20fd2bSAlexei Starovoitov return err; 301db20fd2bSAlexei Starovoitov } 302db20fd2bSAlexei Starovoitov 303db20fd2bSAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */ 304db20fd2bSAlexei Starovoitov #define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key 305db20fd2bSAlexei Starovoitov 306db20fd2bSAlexei Starovoitov static int map_get_next_key(union bpf_attr *attr) 307db20fd2bSAlexei Starovoitov { 308db20fd2bSAlexei Starovoitov void __user *ukey = u64_to_ptr(attr->key); 309db20fd2bSAlexei Starovoitov void __user *unext_key = u64_to_ptr(attr->next_key); 310db20fd2bSAlexei Starovoitov int ufd = attr->map_fd; 311db20fd2bSAlexei Starovoitov struct bpf_map *map; 312db20fd2bSAlexei Starovoitov void *key, *next_key; 313592867bfSDaniel Borkmann struct fd f; 314db20fd2bSAlexei Starovoitov int err; 315db20fd2bSAlexei Starovoitov 316db20fd2bSAlexei Starovoitov if (CHECK_ATTR(BPF_MAP_GET_NEXT_KEY)) 317db20fd2bSAlexei Starovoitov return -EINVAL; 318db20fd2bSAlexei Starovoitov 319592867bfSDaniel Borkmann f = fdget(ufd); 320db20fd2bSAlexei Starovoitov map = bpf_map_get(f); 321db20fd2bSAlexei Starovoitov if (IS_ERR(map)) 322db20fd2bSAlexei Starovoitov return PTR_ERR(map); 323db20fd2bSAlexei Starovoitov 324db20fd2bSAlexei Starovoitov err = -ENOMEM; 325db20fd2bSAlexei Starovoitov key = kmalloc(map->key_size, GFP_USER); 326db20fd2bSAlexei Starovoitov if (!key) 327db20fd2bSAlexei Starovoitov goto err_put; 328db20fd2bSAlexei Starovoitov 329db20fd2bSAlexei Starovoitov err = -EFAULT; 330db20fd2bSAlexei Starovoitov if (copy_from_user(key, ukey, map->key_size) != 0) 331db20fd2bSAlexei Starovoitov goto free_key; 332db20fd2bSAlexei Starovoitov 333db20fd2bSAlexei Starovoitov err = -ENOMEM; 334db20fd2bSAlexei Starovoitov next_key = kmalloc(map->key_size, GFP_USER); 335db20fd2bSAlexei Starovoitov if (!next_key) 336db20fd2bSAlexei Starovoitov goto free_key; 337db20fd2bSAlexei Starovoitov 338db20fd2bSAlexei Starovoitov rcu_read_lock(); 339db20fd2bSAlexei Starovoitov err = map->ops->map_get_next_key(map, key, next_key); 340db20fd2bSAlexei Starovoitov rcu_read_unlock(); 341db20fd2bSAlexei Starovoitov if (err) 342db20fd2bSAlexei Starovoitov goto free_next_key; 343db20fd2bSAlexei Starovoitov 344db20fd2bSAlexei Starovoitov err = -EFAULT; 345db20fd2bSAlexei Starovoitov if (copy_to_user(unext_key, next_key, map->key_size) != 0) 346db20fd2bSAlexei Starovoitov goto free_next_key; 347db20fd2bSAlexei Starovoitov 348db20fd2bSAlexei Starovoitov err = 0; 349db20fd2bSAlexei Starovoitov 350db20fd2bSAlexei Starovoitov free_next_key: 351db20fd2bSAlexei Starovoitov kfree(next_key); 352db20fd2bSAlexei Starovoitov free_key: 353db20fd2bSAlexei Starovoitov kfree(key); 354db20fd2bSAlexei Starovoitov err_put: 355db20fd2bSAlexei Starovoitov fdput(f); 356db20fd2bSAlexei Starovoitov return err; 357db20fd2bSAlexei Starovoitov } 358db20fd2bSAlexei Starovoitov 35909756af4SAlexei Starovoitov static LIST_HEAD(bpf_prog_types); 36009756af4SAlexei Starovoitov 36109756af4SAlexei Starovoitov static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog) 36209756af4SAlexei Starovoitov { 36309756af4SAlexei Starovoitov struct bpf_prog_type_list *tl; 36409756af4SAlexei Starovoitov 36509756af4SAlexei Starovoitov list_for_each_entry(tl, &bpf_prog_types, list_node) { 36609756af4SAlexei Starovoitov if (tl->type == type) { 36709756af4SAlexei Starovoitov prog->aux->ops = tl->ops; 36824701eceSDaniel Borkmann prog->type = type; 36909756af4SAlexei Starovoitov return 0; 37009756af4SAlexei Starovoitov } 37109756af4SAlexei Starovoitov } 37224701eceSDaniel Borkmann 37309756af4SAlexei Starovoitov return -EINVAL; 37409756af4SAlexei Starovoitov } 37509756af4SAlexei Starovoitov 37609756af4SAlexei Starovoitov void bpf_register_prog_type(struct bpf_prog_type_list *tl) 37709756af4SAlexei Starovoitov { 37809756af4SAlexei Starovoitov list_add(&tl->list_node, &bpf_prog_types); 37909756af4SAlexei Starovoitov } 38009756af4SAlexei Starovoitov 3810a542a86SAlexei Starovoitov /* fixup insn->imm field of bpf_call instructions: 3820a542a86SAlexei Starovoitov * if (insn->imm == BPF_FUNC_map_lookup_elem) 3830a542a86SAlexei Starovoitov * insn->imm = bpf_map_lookup_elem - __bpf_call_base; 3840a542a86SAlexei Starovoitov * else if (insn->imm == BPF_FUNC_map_update_elem) 3850a542a86SAlexei Starovoitov * insn->imm = bpf_map_update_elem - __bpf_call_base; 3860a542a86SAlexei Starovoitov * else ... 3870a542a86SAlexei Starovoitov * 3880a542a86SAlexei Starovoitov * this function is called after eBPF program passed verification 3890a542a86SAlexei Starovoitov */ 3900a542a86SAlexei Starovoitov static void fixup_bpf_calls(struct bpf_prog *prog) 3910a542a86SAlexei Starovoitov { 3920a542a86SAlexei Starovoitov const struct bpf_func_proto *fn; 3930a542a86SAlexei Starovoitov int i; 3940a542a86SAlexei Starovoitov 3950a542a86SAlexei Starovoitov for (i = 0; i < prog->len; i++) { 3960a542a86SAlexei Starovoitov struct bpf_insn *insn = &prog->insnsi[i]; 3970a542a86SAlexei Starovoitov 3980a542a86SAlexei Starovoitov if (insn->code == (BPF_JMP | BPF_CALL)) { 3990a542a86SAlexei Starovoitov /* we reach here when program has bpf_call instructions 4000a542a86SAlexei Starovoitov * and it passed bpf_check(), means that 4010a542a86SAlexei Starovoitov * ops->get_func_proto must have been supplied, check it 4020a542a86SAlexei Starovoitov */ 4030a542a86SAlexei Starovoitov BUG_ON(!prog->aux->ops->get_func_proto); 4040a542a86SAlexei Starovoitov 405c46646d0SDaniel Borkmann if (insn->imm == BPF_FUNC_get_route_realm) 406c46646d0SDaniel Borkmann prog->dst_needed = 1; 407*3ad00405SDaniel Borkmann if (insn->imm == BPF_FUNC_get_prandom_u32) 408*3ad00405SDaniel Borkmann bpf_user_rnd_init_once(); 40904fd61abSAlexei Starovoitov if (insn->imm == BPF_FUNC_tail_call) { 41004fd61abSAlexei Starovoitov /* mark bpf_tail_call as different opcode 41104fd61abSAlexei Starovoitov * to avoid conditional branch in 41204fd61abSAlexei Starovoitov * interpeter for every normal call 41304fd61abSAlexei Starovoitov * and to prevent accidental JITing by 41404fd61abSAlexei Starovoitov * JIT compiler that doesn't support 41504fd61abSAlexei Starovoitov * bpf_tail_call yet 41604fd61abSAlexei Starovoitov */ 41704fd61abSAlexei Starovoitov insn->imm = 0; 41804fd61abSAlexei Starovoitov insn->code |= BPF_X; 41904fd61abSAlexei Starovoitov continue; 42004fd61abSAlexei Starovoitov } 42104fd61abSAlexei Starovoitov 4220a542a86SAlexei Starovoitov fn = prog->aux->ops->get_func_proto(insn->imm); 4230a542a86SAlexei Starovoitov /* all functions that have prototype and verifier allowed 4240a542a86SAlexei Starovoitov * programs to call them, must be real in-kernel functions 4250a542a86SAlexei Starovoitov */ 4260a542a86SAlexei Starovoitov BUG_ON(!fn->func); 4270a542a86SAlexei Starovoitov insn->imm = fn->func - __bpf_call_base; 4280a542a86SAlexei Starovoitov } 4290a542a86SAlexei Starovoitov } 4300a542a86SAlexei Starovoitov } 4310a542a86SAlexei Starovoitov 43209756af4SAlexei Starovoitov /* drop refcnt on maps used by eBPF program and free auxilary data */ 43309756af4SAlexei Starovoitov static void free_used_maps(struct bpf_prog_aux *aux) 43409756af4SAlexei Starovoitov { 43509756af4SAlexei Starovoitov int i; 43609756af4SAlexei Starovoitov 43709756af4SAlexei Starovoitov for (i = 0; i < aux->used_map_cnt; i++) 43809756af4SAlexei Starovoitov bpf_map_put(aux->used_maps[i]); 43909756af4SAlexei Starovoitov 44009756af4SAlexei Starovoitov kfree(aux->used_maps); 44109756af4SAlexei Starovoitov } 44209756af4SAlexei Starovoitov 443abf2e7d6SAlexei Starovoitov static void __prog_put_rcu(struct rcu_head *rcu) 444abf2e7d6SAlexei Starovoitov { 445abf2e7d6SAlexei Starovoitov struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu); 446abf2e7d6SAlexei Starovoitov 447abf2e7d6SAlexei Starovoitov free_used_maps(aux); 448abf2e7d6SAlexei Starovoitov bpf_prog_free(aux->prog); 449abf2e7d6SAlexei Starovoitov } 450abf2e7d6SAlexei Starovoitov 451abf2e7d6SAlexei Starovoitov /* version of bpf_prog_put() that is called after a grace period */ 452abf2e7d6SAlexei Starovoitov void bpf_prog_put_rcu(struct bpf_prog *prog) 453abf2e7d6SAlexei Starovoitov { 454abf2e7d6SAlexei Starovoitov if (atomic_dec_and_test(&prog->aux->refcnt)) { 455abf2e7d6SAlexei Starovoitov prog->aux->prog = prog; 456abf2e7d6SAlexei Starovoitov call_rcu(&prog->aux->rcu, __prog_put_rcu); 457abf2e7d6SAlexei Starovoitov } 458abf2e7d6SAlexei Starovoitov } 459abf2e7d6SAlexei Starovoitov 46009756af4SAlexei Starovoitov void bpf_prog_put(struct bpf_prog *prog) 46109756af4SAlexei Starovoitov { 46209756af4SAlexei Starovoitov if (atomic_dec_and_test(&prog->aux->refcnt)) { 46309756af4SAlexei Starovoitov free_used_maps(prog->aux); 46409756af4SAlexei Starovoitov bpf_prog_free(prog); 46509756af4SAlexei Starovoitov } 46609756af4SAlexei Starovoitov } 467e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_put); 46809756af4SAlexei Starovoitov 46909756af4SAlexei Starovoitov static int bpf_prog_release(struct inode *inode, struct file *filp) 47009756af4SAlexei Starovoitov { 47109756af4SAlexei Starovoitov struct bpf_prog *prog = filp->private_data; 47209756af4SAlexei Starovoitov 473abf2e7d6SAlexei Starovoitov bpf_prog_put_rcu(prog); 47409756af4SAlexei Starovoitov return 0; 47509756af4SAlexei Starovoitov } 47609756af4SAlexei Starovoitov 47709756af4SAlexei Starovoitov static const struct file_operations bpf_prog_fops = { 47809756af4SAlexei Starovoitov .release = bpf_prog_release, 47909756af4SAlexei Starovoitov }; 48009756af4SAlexei Starovoitov 48109756af4SAlexei Starovoitov static struct bpf_prog *get_prog(struct fd f) 48209756af4SAlexei Starovoitov { 48309756af4SAlexei Starovoitov struct bpf_prog *prog; 48409756af4SAlexei Starovoitov 48509756af4SAlexei Starovoitov if (!f.file) 48609756af4SAlexei Starovoitov return ERR_PTR(-EBADF); 48709756af4SAlexei Starovoitov 48809756af4SAlexei Starovoitov if (f.file->f_op != &bpf_prog_fops) { 48909756af4SAlexei Starovoitov fdput(f); 49009756af4SAlexei Starovoitov return ERR_PTR(-EINVAL); 49109756af4SAlexei Starovoitov } 49209756af4SAlexei Starovoitov 49309756af4SAlexei Starovoitov prog = f.file->private_data; 49409756af4SAlexei Starovoitov 49509756af4SAlexei Starovoitov return prog; 49609756af4SAlexei Starovoitov } 49709756af4SAlexei Starovoitov 49809756af4SAlexei Starovoitov /* called by sockets/tracing/seccomp before attaching program to an event 49909756af4SAlexei Starovoitov * pairs with bpf_prog_put() 50009756af4SAlexei Starovoitov */ 50109756af4SAlexei Starovoitov struct bpf_prog *bpf_prog_get(u32 ufd) 50209756af4SAlexei Starovoitov { 50309756af4SAlexei Starovoitov struct fd f = fdget(ufd); 50409756af4SAlexei Starovoitov struct bpf_prog *prog; 50509756af4SAlexei Starovoitov 50609756af4SAlexei Starovoitov prog = get_prog(f); 50709756af4SAlexei Starovoitov 50809756af4SAlexei Starovoitov if (IS_ERR(prog)) 50909756af4SAlexei Starovoitov return prog; 51009756af4SAlexei Starovoitov 51109756af4SAlexei Starovoitov atomic_inc(&prog->aux->refcnt); 51209756af4SAlexei Starovoitov fdput(f); 51309756af4SAlexei Starovoitov return prog; 51409756af4SAlexei Starovoitov } 515e2e9b654SDaniel Borkmann EXPORT_SYMBOL_GPL(bpf_prog_get); 51609756af4SAlexei Starovoitov 51709756af4SAlexei Starovoitov /* last field in 'union bpf_attr' used by this command */ 5182541517cSAlexei Starovoitov #define BPF_PROG_LOAD_LAST_FIELD kern_version 51909756af4SAlexei Starovoitov 52009756af4SAlexei Starovoitov static int bpf_prog_load(union bpf_attr *attr) 52109756af4SAlexei Starovoitov { 52209756af4SAlexei Starovoitov enum bpf_prog_type type = attr->prog_type; 52309756af4SAlexei Starovoitov struct bpf_prog *prog; 52409756af4SAlexei Starovoitov int err; 52509756af4SAlexei Starovoitov char license[128]; 52609756af4SAlexei Starovoitov bool is_gpl; 52709756af4SAlexei Starovoitov 52809756af4SAlexei Starovoitov if (CHECK_ATTR(BPF_PROG_LOAD)) 52909756af4SAlexei Starovoitov return -EINVAL; 53009756af4SAlexei Starovoitov 53109756af4SAlexei Starovoitov /* copy eBPF program license from user space */ 53209756af4SAlexei Starovoitov if (strncpy_from_user(license, u64_to_ptr(attr->license), 53309756af4SAlexei Starovoitov sizeof(license) - 1) < 0) 53409756af4SAlexei Starovoitov return -EFAULT; 53509756af4SAlexei Starovoitov license[sizeof(license) - 1] = 0; 53609756af4SAlexei Starovoitov 53709756af4SAlexei Starovoitov /* eBPF programs must be GPL compatible to use GPL-ed functions */ 53809756af4SAlexei Starovoitov is_gpl = license_is_gpl_compatible(license); 53909756af4SAlexei Starovoitov 54009756af4SAlexei Starovoitov if (attr->insn_cnt >= BPF_MAXINSNS) 54109756af4SAlexei Starovoitov return -EINVAL; 54209756af4SAlexei Starovoitov 5432541517cSAlexei Starovoitov if (type == BPF_PROG_TYPE_KPROBE && 5442541517cSAlexei Starovoitov attr->kern_version != LINUX_VERSION_CODE) 5452541517cSAlexei Starovoitov return -EINVAL; 5462541517cSAlexei Starovoitov 54709756af4SAlexei Starovoitov /* plain bpf_prog allocation */ 54809756af4SAlexei Starovoitov prog = bpf_prog_alloc(bpf_prog_size(attr->insn_cnt), GFP_USER); 54909756af4SAlexei Starovoitov if (!prog) 55009756af4SAlexei Starovoitov return -ENOMEM; 55109756af4SAlexei Starovoitov 55209756af4SAlexei Starovoitov prog->len = attr->insn_cnt; 55309756af4SAlexei Starovoitov 55409756af4SAlexei Starovoitov err = -EFAULT; 55509756af4SAlexei Starovoitov if (copy_from_user(prog->insns, u64_to_ptr(attr->insns), 55609756af4SAlexei Starovoitov prog->len * sizeof(struct bpf_insn)) != 0) 55709756af4SAlexei Starovoitov goto free_prog; 55809756af4SAlexei Starovoitov 55909756af4SAlexei Starovoitov prog->orig_prog = NULL; 560a91263d5SDaniel Borkmann prog->jited = 0; 56109756af4SAlexei Starovoitov 56209756af4SAlexei Starovoitov atomic_set(&prog->aux->refcnt, 1); 563a91263d5SDaniel Borkmann prog->gpl_compatible = is_gpl ? 1 : 0; 56409756af4SAlexei Starovoitov 56509756af4SAlexei Starovoitov /* find program type: socket_filter vs tracing_filter */ 56609756af4SAlexei Starovoitov err = find_prog_type(type, prog); 56709756af4SAlexei Starovoitov if (err < 0) 56809756af4SAlexei Starovoitov goto free_prog; 56909756af4SAlexei Starovoitov 57009756af4SAlexei Starovoitov /* run eBPF verifier */ 5719bac3d6dSAlexei Starovoitov err = bpf_check(&prog, attr); 57209756af4SAlexei Starovoitov if (err < 0) 57309756af4SAlexei Starovoitov goto free_used_maps; 57409756af4SAlexei Starovoitov 5750a542a86SAlexei Starovoitov /* fixup BPF_CALL->imm field */ 5760a542a86SAlexei Starovoitov fixup_bpf_calls(prog); 5770a542a86SAlexei Starovoitov 57809756af4SAlexei Starovoitov /* eBPF program is ready to be JITed */ 57904fd61abSAlexei Starovoitov err = bpf_prog_select_runtime(prog); 58004fd61abSAlexei Starovoitov if (err < 0) 58104fd61abSAlexei Starovoitov goto free_used_maps; 58209756af4SAlexei Starovoitov 58309756af4SAlexei Starovoitov err = anon_inode_getfd("bpf-prog", &bpf_prog_fops, prog, O_RDWR | O_CLOEXEC); 58409756af4SAlexei Starovoitov if (err < 0) 58509756af4SAlexei Starovoitov /* failed to allocate fd */ 58609756af4SAlexei Starovoitov goto free_used_maps; 58709756af4SAlexei Starovoitov 58809756af4SAlexei Starovoitov return err; 58909756af4SAlexei Starovoitov 59009756af4SAlexei Starovoitov free_used_maps: 59109756af4SAlexei Starovoitov free_used_maps(prog->aux); 59209756af4SAlexei Starovoitov free_prog: 59309756af4SAlexei Starovoitov bpf_prog_free(prog); 59409756af4SAlexei Starovoitov return err; 59509756af4SAlexei Starovoitov } 59609756af4SAlexei Starovoitov 59799c55f7dSAlexei Starovoitov SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) 59899c55f7dSAlexei Starovoitov { 59999c55f7dSAlexei Starovoitov union bpf_attr attr = {}; 60099c55f7dSAlexei Starovoitov int err; 60199c55f7dSAlexei Starovoitov 60299c55f7dSAlexei Starovoitov /* the syscall is limited to root temporarily. This restriction will be 60399c55f7dSAlexei Starovoitov * lifted when security audit is clean. Note that eBPF+tracing must have 60499c55f7dSAlexei Starovoitov * this restriction, since it may pass kernel data to user space 60599c55f7dSAlexei Starovoitov */ 60699c55f7dSAlexei Starovoitov if (!capable(CAP_SYS_ADMIN)) 60799c55f7dSAlexei Starovoitov return -EPERM; 60899c55f7dSAlexei Starovoitov 60999c55f7dSAlexei Starovoitov if (!access_ok(VERIFY_READ, uattr, 1)) 61099c55f7dSAlexei Starovoitov return -EFAULT; 61199c55f7dSAlexei Starovoitov 61299c55f7dSAlexei Starovoitov if (size > PAGE_SIZE) /* silly large */ 61399c55f7dSAlexei Starovoitov return -E2BIG; 61499c55f7dSAlexei Starovoitov 61599c55f7dSAlexei Starovoitov /* If we're handed a bigger struct than we know of, 61699c55f7dSAlexei Starovoitov * ensure all the unknown bits are 0 - i.e. new 61799c55f7dSAlexei Starovoitov * user-space does not rely on any kernel feature 61899c55f7dSAlexei Starovoitov * extensions we dont know about yet. 61999c55f7dSAlexei Starovoitov */ 62099c55f7dSAlexei Starovoitov if (size > sizeof(attr)) { 62199c55f7dSAlexei Starovoitov unsigned char __user *addr; 62299c55f7dSAlexei Starovoitov unsigned char __user *end; 62399c55f7dSAlexei Starovoitov unsigned char val; 62499c55f7dSAlexei Starovoitov 62599c55f7dSAlexei Starovoitov addr = (void __user *)uattr + sizeof(attr); 62699c55f7dSAlexei Starovoitov end = (void __user *)uattr + size; 62799c55f7dSAlexei Starovoitov 62899c55f7dSAlexei Starovoitov for (; addr < end; addr++) { 62999c55f7dSAlexei Starovoitov err = get_user(val, addr); 63099c55f7dSAlexei Starovoitov if (err) 63199c55f7dSAlexei Starovoitov return err; 63299c55f7dSAlexei Starovoitov if (val) 63399c55f7dSAlexei Starovoitov return -E2BIG; 63499c55f7dSAlexei Starovoitov } 63599c55f7dSAlexei Starovoitov size = sizeof(attr); 63699c55f7dSAlexei Starovoitov } 63799c55f7dSAlexei Starovoitov 63899c55f7dSAlexei Starovoitov /* copy attributes from user space, may be less than sizeof(bpf_attr) */ 63999c55f7dSAlexei Starovoitov if (copy_from_user(&attr, uattr, size) != 0) 64099c55f7dSAlexei Starovoitov return -EFAULT; 64199c55f7dSAlexei Starovoitov 64299c55f7dSAlexei Starovoitov switch (cmd) { 64399c55f7dSAlexei Starovoitov case BPF_MAP_CREATE: 64499c55f7dSAlexei Starovoitov err = map_create(&attr); 64599c55f7dSAlexei Starovoitov break; 646db20fd2bSAlexei Starovoitov case BPF_MAP_LOOKUP_ELEM: 647db20fd2bSAlexei Starovoitov err = map_lookup_elem(&attr); 648db20fd2bSAlexei Starovoitov break; 649db20fd2bSAlexei Starovoitov case BPF_MAP_UPDATE_ELEM: 650db20fd2bSAlexei Starovoitov err = map_update_elem(&attr); 651db20fd2bSAlexei Starovoitov break; 652db20fd2bSAlexei Starovoitov case BPF_MAP_DELETE_ELEM: 653db20fd2bSAlexei Starovoitov err = map_delete_elem(&attr); 654db20fd2bSAlexei Starovoitov break; 655db20fd2bSAlexei Starovoitov case BPF_MAP_GET_NEXT_KEY: 656db20fd2bSAlexei Starovoitov err = map_get_next_key(&attr); 657db20fd2bSAlexei Starovoitov break; 65809756af4SAlexei Starovoitov case BPF_PROG_LOAD: 65909756af4SAlexei Starovoitov err = bpf_prog_load(&attr); 66009756af4SAlexei Starovoitov break; 66199c55f7dSAlexei Starovoitov default: 66299c55f7dSAlexei Starovoitov err = -EINVAL; 66399c55f7dSAlexei Starovoitov break; 66499c55f7dSAlexei Starovoitov } 66599c55f7dSAlexei Starovoitov 66699c55f7dSAlexei Starovoitov return err; 66799c55f7dSAlexei Starovoitov } 668