Skip to content

Commit 1ae80cf

Browse files
Daniel ColascioneAlexei Starovoitov
authored andcommitted
bpf: wait for running BPF programs when updating map-in-map
The map-in-map frequently serves as a mechanism for atomic snapshotting of state that a BPF program might record. The current implementation is dangerous to use in this way, however, since userspace has no way of knowing when all programs that might have retrieved the "old" value of the map may have completed. This change ensures that map update operations on map-in-map map types always wait for all references to the old map to drop before returning to userspace. Signed-off-by: Daniel Colascione <dancol@google.com> Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent ef4ab84 commit 1ae80cf

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

kernel/bpf/syscall.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,17 @@ static int map_lookup_elem(union bpf_attr *attr)
748748
return err;
749749
}
750750

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+
751762
#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
752763

753764
static int map_update_elem(union bpf_attr *attr)
@@ -842,6 +853,7 @@ static int map_update_elem(union bpf_attr *attr)
842853
}
843854
__this_cpu_dec(bpf_prog_active);
844855
preempt_enable();
856+
maybe_wait_bpf_programs(map);
845857
out:
846858
free_value:
847859
kfree(value);
@@ -894,6 +906,7 @@ static int map_delete_elem(union bpf_attr *attr)
894906
rcu_read_unlock();
895907
__this_cpu_dec(bpf_prog_active);
896908
preempt_enable();
909+
maybe_wait_bpf_programs(map);
897910
out:
898911
kfree(key);
899912
err_put:

0 commit comments

Comments
 (0)