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