Skip to content

Commit a7e7501

Browse files
kkdwivediAlexei Starovoitov
authored andcommitted
selftests/bpf: Add test for bpf_timer overwriting crash
Add a test that validates that timer value is not overwritten when doing a copy_map_value call in the kernel. Without the prior fix, this test triggers a crash. Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent a8abb0c commit a7e7501

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <test_progs.h>
3+
#include "timer_crash.skel.h"
4+
5+
enum {
6+
MODE_ARRAY,
7+
MODE_HASH,
8+
};
9+
10+
static void test_timer_crash_mode(int mode)
11+
{
12+
struct timer_crash *skel;
13+
14+
skel = timer_crash__open_and_load();
15+
if (!ASSERT_OK_PTR(skel, "timer_crash__open_and_load"))
16+
return;
17+
skel->bss->pid = getpid();
18+
skel->bss->crash_map = mode;
19+
if (!ASSERT_OK(timer_crash__attach(skel), "timer_crash__attach"))
20+
goto end;
21+
usleep(1);
22+
end:
23+
timer_crash__destroy(skel);
24+
}
25+
26+
void test_timer_crash(void)
27+
{
28+
if (test__start_subtest("array"))
29+
test_timer_crash_mode(MODE_ARRAY);
30+
if (test__start_subtest("hash"))
31+
test_timer_crash_mode(MODE_HASH);
32+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_tracing.h>
5+
#include <bpf/bpf_helpers.h>
6+
7+
struct map_elem {
8+
struct bpf_timer timer;
9+
struct bpf_spin_lock lock;
10+
};
11+
12+
struct {
13+
__uint(type, BPF_MAP_TYPE_ARRAY);
14+
__uint(max_entries, 1);
15+
__type(key, int);
16+
__type(value, struct map_elem);
17+
} amap SEC(".maps");
18+
19+
struct {
20+
__uint(type, BPF_MAP_TYPE_HASH);
21+
__uint(max_entries, 1);
22+
__type(key, int);
23+
__type(value, struct map_elem);
24+
} hmap SEC(".maps");
25+
26+
int pid = 0;
27+
int crash_map = 0; /* 0 for amap, 1 for hmap */
28+
29+
SEC("fentry/do_nanosleep")
30+
int sys_enter(void *ctx)
31+
{
32+
struct map_elem *e, value = {};
33+
void *map = crash_map ? (void *)&hmap : (void *)&amap;
34+
35+
if (bpf_get_current_task_btf()->tgid != pid)
36+
return 0;
37+
38+
*(void **)&value = (void *)0xdeadcaf3;
39+
40+
bpf_map_update_elem(map, &(int){0}, &value, 0);
41+
/* For array map, doing bpf_map_update_elem will do a
42+
* check_and_free_timer_in_array, which will trigger the crash if timer
43+
* pointer was overwritten, for hmap we need to use bpf_timer_cancel.
44+
*/
45+
if (crash_map == 1) {
46+
e = bpf_map_lookup_elem(map, &(int){0});
47+
if (!e)
48+
return 0;
49+
bpf_timer_cancel(&e->timer);
50+
}
51+
return 0;
52+
}
53+
54+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)