aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 84470d1480aa..797a99c7493e 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -463,7 +463,7 @@ int map_check_no_btf(const struct bpf_map *map,
463 return -ENOTSUPP; 463 return -ENOTSUPP;
464} 464}
465 465
466static int map_check_btf(const struct bpf_map *map, const struct btf *btf, 466static int map_check_btf(struct bpf_map *map, const struct btf *btf,
467 u32 btf_key_id, u32 btf_value_id) 467 u32 btf_key_id, u32 btf_value_id)
468{ 468{
469 const struct btf_type *key_type, *value_type; 469 const struct btf_type *key_type, *value_type;
@@ -478,6 +478,22 @@ static int map_check_btf(const struct bpf_map *map, const struct btf *btf,
478 if (!value_type || value_size != map->value_size) 478 if (!value_type || value_size != map->value_size)
479 return -EINVAL; 479 return -EINVAL;
480 480
481 map->spin_lock_off = btf_find_spin_lock(btf, value_type);
482
483 if (map_value_has_spin_lock(map)) {
484 if (map->map_type != BPF_MAP_TYPE_HASH &&
485 map->map_type != BPF_MAP_TYPE_ARRAY &&
486 map->map_type != BPF_MAP_TYPE_CGROUP_STORAGE)
487 return -ENOTSUPP;
488 if (map->spin_lock_off + sizeof(struct bpf_spin_lock) >
489 map->value_size) {
490 WARN_ONCE(1,
491 "verifier bug spin_lock_off %d value_size %d\n",
492 map->spin_lock_off, map->value_size);
493 return -EFAULT;
494 }
495 }
496
481 if (map->ops->map_check_btf) 497 if (map->ops->map_check_btf)
482 ret = map->ops->map_check_btf(map, btf, key_type, value_type); 498 ret = map->ops->map_check_btf(map, btf, key_type, value_type);
483 499
@@ -542,6 +558,8 @@ static int map_create(union bpf_attr *attr)
542 map->btf = btf; 558 map->btf = btf;
543 map->btf_key_type_id = attr->btf_key_type_id; 559 map->btf_key_type_id = attr->btf_key_type_id;
544 map->btf_value_type_id = attr->btf_value_type_id; 560 map->btf_value_type_id = attr->btf_value_type_id;
561 } else {
562 map->spin_lock_off = -EINVAL;
545 } 563 }
546 564
547 err = security_bpf_map_alloc(map); 565 err = security_bpf_map_alloc(map);
@@ -664,7 +682,7 @@ static void *__bpf_copy_key(void __user *ukey, u64 key_size)
664} 682}
665 683
666/* last field in 'union bpf_attr' used by this command */ 684/* last field in 'union bpf_attr' used by this command */
667#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value 685#define BPF_MAP_LOOKUP_ELEM_LAST_FIELD flags
668 686
669static int map_lookup_elem(union bpf_attr *attr) 687static int map_lookup_elem(union bpf_attr *attr)
670{ 688{
@@ -680,6 +698,9 @@ static int map_lookup_elem(union bpf_attr *attr)
680 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) 698 if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM))
681 return -EINVAL; 699 return -EINVAL;
682 700
701 if (attr->flags & ~BPF_F_LOCK)
702 return -EINVAL;
703
683 f = fdget(ufd); 704 f = fdget(ufd);
684 map = __bpf_map_get(f); 705 map = __bpf_map_get(f);
685 if (IS_ERR(map)) 706 if (IS_ERR(map))
@@ -690,6 +711,12 @@ static int map_lookup_elem(union bpf_attr *attr)
690 goto err_put; 711 goto err_put;
691 } 712 }
692 713
714 if ((attr->flags & BPF_F_LOCK) &&
715 !map_value_has_spin_lock(map)) {
716 err = -EINVAL;
717 goto err_put;
718 }
719
693 key = __bpf_copy_key(ukey, map->key_size); 720 key = __bpf_copy_key(ukey, map->key_size);
694 if (IS_ERR(key)) { 721 if (IS_ERR(key)) {
695 err = PTR_ERR(key); 722 err = PTR_ERR(key);
@@ -745,7 +772,13 @@ static int map_lookup_elem(union bpf_attr *attr)
745 err = -ENOENT; 772 err = -ENOENT;
746 } else { 773 } else {
747 err = 0; 774 err = 0;
748 memcpy(value, ptr, value_size); 775 if (attr->flags & BPF_F_LOCK)
776 /* lock 'ptr' and copy everything but lock */
777 copy_map_value_locked(map, value, ptr, true);
778 else
779 copy_map_value(map, value, ptr);
780 /* mask lock, since value wasn't zero inited */
781 check_and_init_map_lock(map, value);
749 } 782 }
750 rcu_read_unlock(); 783 rcu_read_unlock();
751 } 784 }
@@ -808,6 +841,12 @@ static int map_update_elem(union bpf_attr *attr)
808 goto err_put; 841 goto err_put;
809 } 842 }
810 843
844 if ((attr->flags & BPF_F_LOCK) &&
845 !map_value_has_spin_lock(map)) {
846 err = -EINVAL;
847 goto err_put;
848 }
849
811 key = __bpf_copy_key(ukey, map->key_size); 850 key = __bpf_copy_key(ukey, map->key_size);
812 if (IS_ERR(key)) { 851 if (IS_ERR(key)) {
813 err = PTR_ERR(key); 852 err = PTR_ERR(key);