Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 181 lines 3.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3 4#include <vmlinux.h> 5#include <bpf/bpf_helpers.h> 6#include <bpf/bpf_tracing.h> 7#include "bpf_misc.h" 8#include "bpf_experimental.h" 9 10char _license[] SEC("license") = "GPL"; 11 12/* Timer tests */ 13 14struct timer_elem { 15 struct bpf_timer t; 16}; 17 18struct { 19 __uint(type, BPF_MAP_TYPE_ARRAY); 20 __uint(max_entries, 1); 21 __type(key, int); 22 __type(value, struct timer_elem); 23} timer_map SEC(".maps"); 24 25static int timer_cb(void *map, int *key, struct bpf_timer *timer) 26{ 27 u32 data; 28 /* Timer callbacks are never sleepable, even from non-sleepable programs */ 29 bpf_copy_from_user(&data, sizeof(data), NULL); 30 return 0; 31} 32 33SEC("fentry/bpf_fentry_test1") 34__failure __msg("sleepable helper bpf_copy_from_user#{{[0-9]+}} in non-sleepable prog") 35int timer_non_sleepable_prog(void *ctx) 36{ 37 struct timer_elem *val; 38 int key = 0; 39 40 val = bpf_map_lookup_elem(&timer_map, &key); 41 if (!val) 42 return 0; 43 44 bpf_timer_init(&val->t, &timer_map, 0); 45 bpf_timer_set_callback(&val->t, timer_cb); 46 return 0; 47} 48 49SEC("lsm.s/file_open") 50__failure __msg("sleepable helper bpf_copy_from_user#{{[0-9]+}} in non-sleepable prog") 51int timer_sleepable_prog(void *ctx) 52{ 53 struct timer_elem *val; 54 int key = 0; 55 56 val = bpf_map_lookup_elem(&timer_map, &key); 57 if (!val) 58 return 0; 59 60 bpf_timer_init(&val->t, &timer_map, 0); 61 bpf_timer_set_callback(&val->t, timer_cb); 62 return 0; 63} 64 65/* Workqueue tests */ 66 67struct wq_elem { 68 struct bpf_wq w; 69}; 70 71struct { 72 __uint(type, BPF_MAP_TYPE_ARRAY); 73 __uint(max_entries, 1); 74 __type(key, int); 75 __type(value, struct wq_elem); 76} wq_map SEC(".maps"); 77 78static int wq_cb(void *map, int *key, void *value) 79{ 80 u32 data; 81 /* Workqueue callbacks are always sleepable, even from non-sleepable programs */ 82 bpf_copy_from_user(&data, sizeof(data), NULL); 83 return 0; 84} 85 86SEC("fentry/bpf_fentry_test1") 87__success 88int wq_non_sleepable_prog(void *ctx) 89{ 90 struct wq_elem *val; 91 int key = 0; 92 93 val = bpf_map_lookup_elem(&wq_map, &key); 94 if (!val) 95 return 0; 96 97 if (bpf_wq_init(&val->w, &wq_map, 0) != 0) 98 return 0; 99 if (bpf_wq_set_callback(&val->w, wq_cb, 0) != 0) 100 return 0; 101 return 0; 102} 103 104SEC("lsm.s/file_open") 105__success 106int wq_sleepable_prog(void *ctx) 107{ 108 struct wq_elem *val; 109 int key = 0; 110 111 val = bpf_map_lookup_elem(&wq_map, &key); 112 if (!val) 113 return 0; 114 115 if (bpf_wq_init(&val->w, &wq_map, 0) != 0) 116 return 0; 117 if (bpf_wq_set_callback(&val->w, wq_cb, 0) != 0) 118 return 0; 119 return 0; 120} 121 122/* Task work tests */ 123 124struct task_work_elem { 125 struct bpf_task_work tw; 126}; 127 128struct { 129 __uint(type, BPF_MAP_TYPE_ARRAY); 130 __uint(max_entries, 1); 131 __type(key, int); 132 __type(value, struct task_work_elem); 133} task_work_map SEC(".maps"); 134 135static int task_work_cb(struct bpf_map *map, void *key, void *value) 136{ 137 u32 data; 138 /* Task work callbacks are always sleepable, even from non-sleepable programs */ 139 bpf_copy_from_user(&data, sizeof(data), NULL); 140 return 0; 141} 142 143SEC("fentry/bpf_fentry_test1") 144__success 145int task_work_non_sleepable_prog(void *ctx) 146{ 147 struct task_work_elem *val; 148 struct task_struct *task; 149 int key = 0; 150 151 val = bpf_map_lookup_elem(&task_work_map, &key); 152 if (!val) 153 return 0; 154 155 task = bpf_get_current_task_btf(); 156 if (!task) 157 return 0; 158 159 bpf_task_work_schedule_resume(task, &val->tw, &task_work_map, task_work_cb); 160 return 0; 161} 162 163SEC("lsm.s/file_open") 164__success 165int task_work_sleepable_prog(void *ctx) 166{ 167 struct task_work_elem *val; 168 struct task_struct *task; 169 int key = 0; 170 171 val = bpf_map_lookup_elem(&task_work_map, &key); 172 if (!val) 173 return 0; 174 175 task = bpf_get_current_task_btf(); 176 if (!task) 177 return 0; 178 179 bpf_task_work_schedule_resume(task, &val->tw, &task_work_map, task_work_cb); 180 return 0; 181}