diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 4f416234251f..53968f82b919 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -748,6 +748,17 @@ err_put: | |||
748 | return err; | 748 | return err; |
749 | } | 749 | } |
750 | 750 | ||
751 | static void maybe_wait_bpf_programs(struct bpf_map *map) | ||
752 | { | ||
753 | /* Wait for any running BPF programs to complete so that | ||
754 | * userspace, when we return to it, knows that all programs | ||
755 | * that could be running use the new map value. | ||
756 | */ | ||
757 | if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS || | ||
758 | map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS) | ||
759 | synchronize_rcu(); | ||
760 | } | ||
761 | |||
751 | #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags | 762 | #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags |
752 | 763 | ||
753 | static int map_update_elem(union bpf_attr *attr) | 764 | static int map_update_elem(union bpf_attr *attr) |
@@ -842,6 +853,7 @@ static int map_update_elem(union bpf_attr *attr) | |||
842 | } | 853 | } |
843 | __this_cpu_dec(bpf_prog_active); | 854 | __this_cpu_dec(bpf_prog_active); |
844 | preempt_enable(); | 855 | preempt_enable(); |
856 | maybe_wait_bpf_programs(map); | ||
845 | out: | 857 | out: |
846 | free_value: | 858 | free_value: |
847 | kfree(value); | 859 | kfree(value); |
@@ -894,6 +906,7 @@ static int map_delete_elem(union bpf_attr *attr) | |||
894 | rcu_read_unlock(); | 906 | rcu_read_unlock(); |
895 | __this_cpu_dec(bpf_prog_active); | 907 | __this_cpu_dec(bpf_prog_active); |
896 | preempt_enable(); | 908 | preempt_enable(); |
909 | maybe_wait_bpf_programs(map); | ||
897 | out: | 910 | out: |
898 | kfree(key); | 911 | kfree(key); |
899 | err_put: | 912 | err_put: |