xref: /linux/tools/testing/selftests/bpf/progs/timer_start_delete_race.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1*b135beb0SAlexei Starovoitov // SPDX-License-Identifier: GPL-2.0
2*b135beb0SAlexei Starovoitov /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3*b135beb0SAlexei Starovoitov #include <linux/bpf.h>
4*b135beb0SAlexei Starovoitov #include <time.h>
5*b135beb0SAlexei Starovoitov #include <bpf/bpf_helpers.h>
6*b135beb0SAlexei Starovoitov 
7*b135beb0SAlexei Starovoitov #define ITER_CNT 2000
8*b135beb0SAlexei Starovoitov 
9*b135beb0SAlexei Starovoitov struct map_value {
10*b135beb0SAlexei Starovoitov 	struct bpf_timer timer;
11*b135beb0SAlexei Starovoitov };
12*b135beb0SAlexei Starovoitov 
13*b135beb0SAlexei Starovoitov struct {
14*b135beb0SAlexei Starovoitov 	__uint(type, BPF_MAP_TYPE_ARRAY);
15*b135beb0SAlexei Starovoitov 	__type(key, int);
16*b135beb0SAlexei Starovoitov 	__type(value, struct map_value);
17*b135beb0SAlexei Starovoitov 	__uint(max_entries, 1);
18*b135beb0SAlexei Starovoitov } timer_map SEC(".maps");
19*b135beb0SAlexei Starovoitov 
20*b135beb0SAlexei Starovoitov long cb_cnt;
21*b135beb0SAlexei Starovoitov 
22*b135beb0SAlexei Starovoitov /*
23*b135beb0SAlexei Starovoitov  * Timer callback that accesses the map value.
24*b135beb0SAlexei Starovoitov  * If the race bug exists and this runs on freed memory,
25*b135beb0SAlexei Starovoitov  * KASAN should detect it.
26*b135beb0SAlexei Starovoitov  */
27*b135beb0SAlexei Starovoitov static int timer_cb(void *map, int *key, struct map_value *value)
28*b135beb0SAlexei Starovoitov {
29*b135beb0SAlexei Starovoitov 	__sync_fetch_and_add(&cb_cnt, 1);
30*b135beb0SAlexei Starovoitov 	return 0;
31*b135beb0SAlexei Starovoitov }
32*b135beb0SAlexei Starovoitov 
33*b135beb0SAlexei Starovoitov SEC("syscall")
34*b135beb0SAlexei Starovoitov int start_timer(void *ctx)
35*b135beb0SAlexei Starovoitov {
36*b135beb0SAlexei Starovoitov 	struct map_value *value;
37*b135beb0SAlexei Starovoitov 	int i;
38*b135beb0SAlexei Starovoitov 
39*b135beb0SAlexei Starovoitov 	for (i = 0; i < ITER_CNT; i++) {
40*b135beb0SAlexei Starovoitov 		int key = 0;
41*b135beb0SAlexei Starovoitov 
42*b135beb0SAlexei Starovoitov 		value = bpf_map_lookup_elem(&timer_map, &key);
43*b135beb0SAlexei Starovoitov 		/* hey claude, no if (!value) here. The verifier got smarter */
44*b135beb0SAlexei Starovoitov 
45*b135beb0SAlexei Starovoitov 		bpf_timer_init(&value->timer, &timer_map, CLOCK_MONOTONIC);
46*b135beb0SAlexei Starovoitov 		bpf_timer_set_callback(&value->timer, timer_cb);
47*b135beb0SAlexei Starovoitov 		bpf_timer_start(&value->timer, 100000000, 0);
48*b135beb0SAlexei Starovoitov 	}
49*b135beb0SAlexei Starovoitov 	return 0;
50*b135beb0SAlexei Starovoitov }
51*b135beb0SAlexei Starovoitov 
52*b135beb0SAlexei Starovoitov SEC("syscall")
53*b135beb0SAlexei Starovoitov int delete_elem(void *ctx)
54*b135beb0SAlexei Starovoitov {
55*b135beb0SAlexei Starovoitov 	int i;
56*b135beb0SAlexei Starovoitov 
57*b135beb0SAlexei Starovoitov 	for (i = 0; i < ITER_CNT; i++) {
58*b135beb0SAlexei Starovoitov 		int key = 0;
59*b135beb0SAlexei Starovoitov 
60*b135beb0SAlexei Starovoitov 		bpf_map_delete_elem(&timer_map, &key);
61*b135beb0SAlexei Starovoitov 	}
62*b135beb0SAlexei Starovoitov 
63*b135beb0SAlexei Starovoitov 	return 0;
64*b135beb0SAlexei Starovoitov }
65*b135beb0SAlexei Starovoitov 
66*b135beb0SAlexei Starovoitov char _license[] SEC("license") = "GPL";
67