1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
5 #include <bpf/bpf_helpers.h>
6 #include <bpf/bpf_tracing.h>
7 #include "bpf_tracing_net.h"
10 char _license[] SEC("license") = "GPL";
13 __uint(type, BPF_MAP_TYPE_TASK_STORAGE);
14 __uint(map_flags, BPF_F_NO_PREALLOC);
19 __u32 user_data, key_serial, target_pid;
20 __u64 flags, task_storage_val, cgroup_id;
22 struct bpf_key *bpf_lookup_user_key(__u32 serial, __u64 flags) __ksym;
23 void bpf_key_put(struct bpf_key *key) __ksym;
24 void bpf_rcu_read_lock(void) __ksym;
25 void bpf_rcu_read_unlock(void) __ksym;
26 struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym;
27 void bpf_task_release(struct task_struct *p) __ksym;
29 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
30 int get_cgroup_id(void *ctx)
32 struct task_struct *task;
34 task = bpf_get_current_task_btf();
35 if (task->pid != target_pid)
38 /* simulate bpf_get_current_cgroup_id() helper */
40 cgroup_id = task->cgroups->dfl_cgrp->kn->id;
41 bpf_rcu_read_unlock();
45 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
46 int task_succ(void *ctx)
48 struct task_struct *task, *real_parent;
52 task = bpf_get_current_task_btf();
53 if (task->pid != target_pid)
57 /* region including helper using rcu ptr real_parent */
58 real_parent = task->real_parent;
59 ptr = bpf_task_storage_get(&map_a, real_parent, &init_val,
60 BPF_LOCAL_STORAGE_GET_F_CREATE);
63 ptr = bpf_task_storage_get(&map_a, real_parent, 0, 0);
66 task_storage_val = *ptr;
68 bpf_rcu_read_unlock();
72 SEC("?fentry.s/" SYS_PREFIX "sys_nanosleep")
73 int no_lock(void *ctx)
75 struct task_struct *task, *real_parent;
77 /* no bpf_rcu_read_lock(), old code still works */
78 task = bpf_get_current_task_btf();
79 real_parent = task->real_parent;
80 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
84 SEC("?fentry.s/" SYS_PREFIX "sys_nanosleep")
85 int two_regions(void *ctx)
87 struct task_struct *task, *real_parent;
90 task = bpf_get_current_task_btf();
92 bpf_rcu_read_unlock();
94 real_parent = task->real_parent;
95 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
96 bpf_rcu_read_unlock();
100 SEC("?fentry/" SYS_PREFIX "sys_getpgid")
101 int non_sleepable_1(void *ctx)
103 struct task_struct *task, *real_parent;
105 task = bpf_get_current_task_btf();
107 real_parent = task->real_parent;
108 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
109 bpf_rcu_read_unlock();
113 SEC("?fentry/" SYS_PREFIX "sys_getpgid")
114 int non_sleepable_2(void *ctx)
116 struct task_struct *task, *real_parent;
119 task = bpf_get_current_task_btf();
120 bpf_rcu_read_unlock();
123 real_parent = task->real_parent;
124 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
125 bpf_rcu_read_unlock();
129 SEC("?fentry.s/" SYS_PREFIX "sys_nanosleep")
130 int task_acquire(void *ctx)
132 struct task_struct *task, *real_parent;
134 task = bpf_get_current_task_btf();
136 real_parent = task->real_parent;
137 /* acquire a reference which can be used outside rcu read lock region */
138 real_parent = bpf_task_acquire(real_parent);
139 bpf_rcu_read_unlock();
140 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
141 bpf_task_release(real_parent);
145 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
146 int miss_lock(void *ctx)
148 struct task_struct *task;
149 struct css_set *cgroups;
150 struct cgroup *dfl_cgrp;
152 /* missing bpf_rcu_read_lock() */
153 task = bpf_get_current_task_btf();
155 (void)bpf_task_storage_get(&map_a, task, 0, 0);
156 bpf_rcu_read_unlock();
157 bpf_rcu_read_unlock();
161 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
162 int miss_unlock(void *ctx)
164 struct task_struct *task;
165 struct css_set *cgroups;
166 struct cgroup *dfl_cgrp;
168 /* missing bpf_rcu_read_unlock() */
169 task = bpf_get_current_task_btf();
171 (void)bpf_task_storage_get(&map_a, task, 0, 0);
175 SEC("?fentry/" SYS_PREFIX "sys_getpgid")
176 int non_sleepable_rcu_mismatch(void *ctx)
178 struct task_struct *task, *real_parent;
180 task = bpf_get_current_task_btf();
181 /* non-sleepable: missing bpf_rcu_read_unlock() in one path */
183 real_parent = task->real_parent;
184 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
186 bpf_rcu_read_unlock();
190 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
191 int inproper_sleepable_helper(void *ctx)
193 struct task_struct *task, *real_parent;
194 struct pt_regs *regs;
198 task = bpf_get_current_task_btf();
199 /* sleepable helper in rcu read lock region */
201 real_parent = task->real_parent;
202 regs = (struct pt_regs *)bpf_task_pt_regs(real_parent);
204 bpf_rcu_read_unlock();
208 ptr = (void *)PT_REGS_IP(regs);
209 (void)bpf_copy_from_user_task(&value, sizeof(uint32_t), ptr, task, 0);
211 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
212 bpf_rcu_read_unlock();
217 int BPF_PROG(inproper_sleepable_kfunc, int cmd, union bpf_attr *attr, unsigned int size)
219 struct bpf_key *bkey;
221 /* sleepable kfunc in rcu read lock region */
223 bkey = bpf_lookup_user_key(key_serial, flags);
224 bpf_rcu_read_unlock();
232 SEC("?fentry.s/" SYS_PREFIX "sys_nanosleep")
233 int nested_rcu_region(void *ctx)
235 struct task_struct *task, *real_parent;
237 /* nested rcu read lock regions */
238 task = bpf_get_current_task_btf();
241 real_parent = task->real_parent;
242 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
243 bpf_rcu_read_unlock();
244 bpf_rcu_read_unlock();
248 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
249 int task_untrusted_non_rcuptr(void *ctx)
251 struct task_struct *task, *last_wakee;
253 task = bpf_get_current_task_btf();
255 /* the pointer last_wakee marked as untrusted */
256 last_wakee = task->real_parent->last_wakee;
257 (void)bpf_task_storage_get(&map_a, last_wakee, 0, 0);
258 bpf_rcu_read_unlock();
262 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
263 int task_untrusted_rcuptr(void *ctx)
265 struct task_struct *task, *real_parent;
267 task = bpf_get_current_task_btf();
269 real_parent = task->real_parent;
270 bpf_rcu_read_unlock();
271 /* helper use of rcu ptr outside the rcu read lock region */
272 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
276 SEC("?fentry.s/" SYS_PREFIX "sys_nanosleep")
277 int cross_rcu_region(void *ctx)
279 struct task_struct *task, *real_parent;
281 /* rcu ptr define/use in different regions */
282 task = bpf_get_current_task_btf();
284 real_parent = task->real_parent;
285 bpf_rcu_read_unlock();
287 (void)bpf_task_storage_get(&map_a, real_parent, 0, 0);
288 bpf_rcu_read_unlock();