162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <vmlinux.h>
462306a36Sopenharmony_ci#include <bpf/bpf_tracing.h>
562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_cistruct map_elem {
862306a36Sopenharmony_ci	struct bpf_timer timer;
962306a36Sopenharmony_ci	struct bpf_spin_lock lock;
1062306a36Sopenharmony_ci};
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistruct {
1362306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_ARRAY);
1462306a36Sopenharmony_ci	__uint(max_entries, 1);
1562306a36Sopenharmony_ci	__type(key, int);
1662306a36Sopenharmony_ci	__type(value, struct map_elem);
1762306a36Sopenharmony_ci} amap SEC(".maps");
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct {
2062306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_HASH);
2162306a36Sopenharmony_ci	__uint(max_entries, 1);
2262306a36Sopenharmony_ci	__type(key, int);
2362306a36Sopenharmony_ci	__type(value, struct map_elem);
2462306a36Sopenharmony_ci} hmap SEC(".maps");
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciint pid = 0;
2762306a36Sopenharmony_ciint crash_map = 0; /* 0 for amap, 1 for hmap */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciSEC("fentry/do_nanosleep")
3062306a36Sopenharmony_ciint sys_enter(void *ctx)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct map_elem *e, value = {};
3362306a36Sopenharmony_ci	void *map = crash_map ? (void *)&hmap : (void *)&amap;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (bpf_get_current_task_btf()->tgid != pid)
3662306a36Sopenharmony_ci		return 0;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	*(void **)&value = (void *)0xdeadcaf3;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	bpf_map_update_elem(map, &(int){0}, &value, 0);
4162306a36Sopenharmony_ci	/* For array map, doing bpf_map_update_elem will do a
4262306a36Sopenharmony_ci	 * check_and_free_timer_in_array, which will trigger the crash if timer
4362306a36Sopenharmony_ci	 * pointer was overwritten, for hmap we need to use bpf_timer_cancel.
4462306a36Sopenharmony_ci	 */
4562306a36Sopenharmony_ci	if (crash_map == 1) {
4662306a36Sopenharmony_ci		e = bpf_map_lookup_elem(map, &(int){0});
4762306a36Sopenharmony_ci		if (!e)
4862306a36Sopenharmony_ci			return 0;
4962306a36Sopenharmony_ci		bpf_timer_cancel(&e->timer);
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	return 0;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
55