diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index b29e6dc44650..0834958f1dc4 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -682,7 +682,7 @@ static void *__bpf_copy_key(void __user *ukey, u64 key_size) | |||
682 | } | 682 | } |
683 | 683 | ||
684 | /* last field in 'union bpf_attr' used by this command */ | 684 | /* last field in 'union bpf_attr' used by this command */ |
685 | #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value | 685 | #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD flags |
686 | 686 | ||
687 | static int map_lookup_elem(union bpf_attr *attr) | 687 | static int map_lookup_elem(union bpf_attr *attr) |
688 | { | 688 | { |
@@ -698,6 +698,9 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
698 | if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) | 698 | if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) |
699 | return -EINVAL; | 699 | return -EINVAL; |
700 | 700 | ||
701 | if (attr->flags & ~BPF_F_LOCK) | ||
702 | return -EINVAL; | ||
703 | |||
701 | f = fdget(ufd); | 704 | f = fdget(ufd); |
702 | map = __bpf_map_get(f); | 705 | map = __bpf_map_get(f); |
703 | if (IS_ERR(map)) | 706 | if (IS_ERR(map)) |
@@ -708,6 +711,12 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
708 | goto err_put; | 711 | goto err_put; |
709 | } | 712 | } |
710 | 713 | ||
714 | if ((attr->flags & BPF_F_LOCK) && | ||
715 | !map_value_has_spin_lock(map)) { | ||
716 | err = -EINVAL; | ||
717 | goto err_put; | ||
718 | } | ||
719 | |||
711 | key = __bpf_copy_key(ukey, map->key_size); | 720 | key = __bpf_copy_key(ukey, map->key_size); |
712 | if (IS_ERR(key)) { | 721 | if (IS_ERR(key)) { |
713 | err = PTR_ERR(key); | 722 | err = PTR_ERR(key); |
@@ -758,7 +767,13 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
758 | err = -ENOENT; | 767 | err = -ENOENT; |
759 | } else { | 768 | } else { |
760 | err = 0; | 769 | err = 0; |
761 | copy_map_value(map, value, ptr); | 770 | if (attr->flags & BPF_F_LOCK) |
771 | /* lock 'ptr' and copy everything but lock */ | ||
772 | copy_map_value_locked(map, value, ptr, true); | ||
773 | else | ||
774 | copy_map_value(map, value, ptr); | ||
775 | /* mask lock, since value wasn't zero inited */ | ||
776 | check_and_init_map_lock(map, value); | ||
762 | } | 777 | } |
763 | rcu_read_unlock(); | 778 | rcu_read_unlock(); |
764 | } | 779 | } |
@@ -818,6 +833,12 @@ static int map_update_elem(union bpf_attr *attr) | |||
818 | goto err_put; | 833 | goto err_put; |
819 | } | 834 | } |
820 | 835 | ||
836 | if ((attr->flags & BPF_F_LOCK) && | ||
837 | !map_value_has_spin_lock(map)) { | ||
838 | err = -EINVAL; | ||
839 | goto err_put; | ||
840 | } | ||
841 | |||
821 | key = __bpf_copy_key(ukey, map->key_size); | 842 | key = __bpf_copy_key(ukey, map->key_size); |
822 | if (IS_ERR(key)) { | 843 | if (IS_ERR(key)) { |
823 | err = PTR_ERR(key); | 844 | err = PTR_ERR(key); |