Skip to content

Commit

Permalink
selftests/bpf: add test for softlock when modifying hashmap while ite…
Browse files Browse the repository at this point in the history
…rating

Add test that modifies the map while it's being iterated in such a way that
hangs the kernel thread unless the _safe fix is applied to
bpf_for_each_hash_elem.

Signed-off-by: Brandon Kammerdiener <brandon.kammerdiener@intel.com>
Link: https://lore.kernel.org/r/20250424153246.141677-3-brandon.kammerdiener@intel.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Hou Tao <houtao1@huawei.com>
  • Loading branch information
Brandon Kammerdiener authored and Alexei Starovoitov committed Apr 25, 2025
1 parent 75673fd commit 3d9c463
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
37 changes: 37 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/for_each.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "for_each_array_map_elem.skel.h"
#include "for_each_map_elem_write_key.skel.h"
#include "for_each_multi_maps.skel.h"
#include "for_each_hash_modify.skel.h"

static unsigned int duration;

Expand Down Expand Up @@ -203,6 +204,40 @@ static void test_multi_maps(void)
for_each_multi_maps__destroy(skel);
}

static void test_hash_modify(void)
{
struct for_each_hash_modify *skel;
int max_entries, i, err;
__u64 key, val;

LIBBPF_OPTS(bpf_test_run_opts, topts,
.data_in = &pkt_v4,
.data_size_in = sizeof(pkt_v4),
.repeat = 1
);

skel = for_each_hash_modify__open_and_load();
if (!ASSERT_OK_PTR(skel, "for_each_hash_modify__open_and_load"))
return;

max_entries = bpf_map__max_entries(skel->maps.hashmap);
for (i = 0; i < max_entries; i++) {
key = i;
val = i;
err = bpf_map__update_elem(skel->maps.hashmap, &key, sizeof(key),
&val, sizeof(val), BPF_ANY);
if (!ASSERT_OK(err, "map_update"))
goto out;
}

err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.test_pkt_access), &topts);
ASSERT_OK(err, "bpf_prog_test_run_opts");
ASSERT_OK(topts.retval, "retval");

out:
for_each_hash_modify__destroy(skel);
}

void test_for_each(void)
{
if (test__start_subtest("hash_map"))
Expand All @@ -213,4 +248,6 @@ void test_for_each(void)
test_write_map_key();
if (test__start_subtest("multi_maps"))
test_multi_maps();
if (test__start_subtest("hash_modify"))
test_hash_modify();
}
30 changes: 30 additions & 0 deletions tools/testing/selftests/bpf/progs/for_each_hash_modify.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025 Intel Corporation */
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

char _license[] SEC("license") = "GPL";

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 128);
__type(key, __u64);
__type(value, __u64);
} hashmap SEC(".maps");

static int cb(struct bpf_map *map, __u64 *key, __u64 *val, void *arg)
{
bpf_map_delete_elem(map, key);
bpf_map_update_elem(map, key, val, 0);
return 0;
}

SEC("tc")
int test_pkt_access(struct __sk_buff *skb)
{
(void)skb;

bpf_for_each_map_elem(&hashmap, cb, NULL, 0);

return 0;
}

0 comments on commit 3d9c463

Please sign in to comment.