1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ 3 4 #include <vmlinux.h> 5 #include <bpf/bpf_tracing.h> 6 #include <bpf/bpf_helpers.h> 7 8 #include "../bpf_experimental.h" 9 #include "bpf_misc.h" 10 #include "task_kfunc_common.h" 11 12 char _license[] SEC("license") = "GPL"; 13 14 /* Prototype for all of the program trace events below: 15 * 16 * TRACE_EVENT(task_newtask, 17 * TP_PROTO(struct task_struct *p, u64 clone_flags) 18 */ 19 20 static struct __tasks_kfunc_map_value *insert_lookup_task(struct task_struct *task) 21 { 22 int status; 23 24 status = tasks_kfunc_map_insert(task); 25 if (status) 26 return NULL; 27 28 return tasks_kfunc_map_value_lookup(task); 29 } 30 31 SEC("tp_btf/task_newtask") 32 __failure __msg("Possibly NULL pointer passed to trusted R1") 33 int BPF_PROG(task_kfunc_acquire_untrusted, struct task_struct *task, u64 clone_flags) 34 { 35 struct task_struct *acquired; 36 struct __tasks_kfunc_map_value *v; 37 38 v = insert_lookup_task(task); 39 if (!v) 40 return 0; 41 42 /* Can't invoke bpf_task_acquire() on an untrusted pointer. */ 43 acquired = bpf_task_acquire(v->task); 44 if (!acquired) 45 return 0; 46 47 bpf_task_release(acquired); 48 49 return 0; 50 } 51 52 SEC("tp_btf/task_newtask") 53 __failure __msg("R1 pointer type STRUCT task_struct must point") 54 int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags) 55 { 56 struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags; 57 58 /* Can't invoke bpf_task_acquire() on a random frame pointer. */ 59 acquired = bpf_task_acquire((struct task_struct *)&stack_task); 60 if (!acquired) 61 return 0; 62 63 bpf_task_release(acquired); 64 65 return 0; 66 } 67 68 SEC("kretprobe/free_task") 69 __failure __msg("calling kernel function bpf_task_acquire is not allowed") 70 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe, struct task_struct *task, u64 clone_flags) 71 { 72 struct task_struct *acquired; 73 74 /* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */ 75 acquired = bpf_task_acquire(task); 76 if (!acquired) 77 return 0; 78 bpf_task_release(acquired); 79 80 return 0; 81 } 82 83 SEC("kretprobe/free_task") 84 __failure __msg("calling kernel function bpf_task_acquire is not allowed") 85 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe_rcu, struct task_struct *task, u64 clone_flags) 86 { 87 struct task_struct *acquired; 88 89 bpf_rcu_read_lock(); 90 if (!task) { 91 bpf_rcu_read_unlock(); 92 return 0; 93 } 94 /* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */ 95 acquired = bpf_task_acquire(task); 96 if (acquired) 97 bpf_task_release(acquired); 98 bpf_rcu_read_unlock(); 99 100 return 0; 101 } 102 103 SEC("tp_btf/task_newtask") 104 __failure __msg("Possibly NULL pointer passed to trusted R1") 105 int BPF_PROG(task_kfunc_acquire_null, struct task_struct *task, u64 clone_flags) 106 { 107 struct task_struct *acquired; 108 109 /* Can't invoke bpf_task_acquire() on a NULL pointer. */ 110 acquired = bpf_task_acquire(NULL); 111 if (!acquired) 112 return 0; 113 bpf_task_release(acquired); 114 115 return 0; 116 } 117 118 SEC("tp_btf/task_newtask") 119 __failure __msg("Unreleased reference") 120 int BPF_PROG(task_kfunc_acquire_unreleased, struct task_struct *task, u64 clone_flags) 121 { 122 struct task_struct *acquired; 123 124 acquired = bpf_task_acquire(task); 125 126 /* Acquired task is never released. */ 127 __sink(acquired); 128 129 return 0; 130 } 131 132 SEC("tp_btf/task_newtask") 133 __failure __msg("Unreleased reference") 134 int BPF_PROG(task_kfunc_xchg_unreleased, struct task_struct *task, u64 clone_flags) 135 { 136 struct task_struct *kptr; 137 struct __tasks_kfunc_map_value *v; 138 139 v = insert_lookup_task(task); 140 if (!v) 141 return 0; 142 143 kptr = bpf_kptr_xchg(&v->task, NULL); 144 if (!kptr) 145 return 0; 146 147 /* Kptr retrieved from map is never released. */ 148 149 return 0; 150 } 151 152 SEC("tp_btf/task_newtask") 153 __failure __msg("Possibly NULL pointer passed to trusted R1") 154 int BPF_PROG(task_kfunc_acquire_release_no_null_check, struct task_struct *task, u64 clone_flags) 155 { 156 struct task_struct *acquired; 157 158 acquired = bpf_task_acquire(task); 159 /* Can't invoke bpf_task_release() on an acquired task without a NULL check. */ 160 bpf_task_release(acquired); 161 162 return 0; 163 } 164 165 SEC("tp_btf/task_newtask") 166 __failure __msg("Possibly NULL pointer passed to trusted R1") 167 int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_flags) 168 { 169 struct __tasks_kfunc_map_value *v; 170 171 v = insert_lookup_task(task); 172 if (!v) 173 return 0; 174 175 /* Can't invoke bpf_task_release() on an untrusted pointer. */ 176 bpf_task_release(v->task); 177 178 return 0; 179 } 180 181 SEC("tp_btf/task_newtask") 182 __failure __msg("release kfunc bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1") 183 int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags) 184 { 185 struct task_struct *acquired = (struct task_struct *)&clone_flags; 186 187 /* Cannot release random frame pointer. */ 188 bpf_task_release(acquired); 189 190 return 0; 191 } 192 193 SEC("tp_btf/task_newtask") 194 __failure __msg("Possibly NULL pointer passed to trusted R1") 195 int BPF_PROG(task_kfunc_release_null, struct task_struct *task, u64 clone_flags) 196 { 197 struct __tasks_kfunc_map_value local, *v; 198 long status; 199 struct task_struct *acquired, *old; 200 s32 pid; 201 202 status = bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid); 203 if (status) 204 return 0; 205 206 local.task = NULL; 207 status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST); 208 if (status) 209 return status; 210 211 v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid); 212 if (!v) 213 return -ENOENT; 214 215 acquired = bpf_task_acquire(task); 216 if (!acquired) 217 return -EEXIST; 218 219 old = bpf_kptr_xchg(&v->task, acquired); 220 221 /* old cannot be passed to bpf_task_release() without a NULL check. */ 222 bpf_task_release(old); 223 224 return 0; 225 } 226 227 SEC("tp_btf/task_newtask") 228 __failure __msg("release kfunc bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1") 229 int BPF_PROG(task_kfunc_release_unacquired, struct task_struct *task, u64 clone_flags) 230 { 231 /* Cannot release trusted task pointer which was not acquired. */ 232 bpf_task_release(task); 233 234 return 0; 235 } 236 237 SEC("tp_btf/task_newtask") 238 __failure __msg("bpf_obj_drop cannot be used in tracing programs on types with NMI unsafe fields") 239 int BPF_PROG(task_kfunc_obj_drop_with_kptr, struct task_struct *task, u64 clone_flags) 240 { 241 struct __tasks_kfunc_map_value *local; 242 243 local = bpf_obj_new(typeof(*local)); 244 if (!local) 245 return 0; 246 247 bpf_obj_drop(local); 248 return 0; 249 } 250 251 SEC("tp_btf/task_newtask") 252 __failure __msg("bpf_obj_drop cannot be used in tracing programs on types with NMI unsafe fields") 253 int BPF_PROG(task_kfunc_obj_drop_nmi_with_kptr, struct task_struct *task, 254 u64 clone_flags) 255 { 256 struct __tasks_kfunc_map_value *local; 257 struct task_struct *acquired, *old; 258 259 (void)clone_flags; 260 261 local = bpf_obj_new(typeof(*local)); 262 if (!local) 263 return 0; 264 265 acquired = bpf_task_acquire(task); 266 if (acquired) { 267 old = bpf_kptr_xchg(&local->task, acquired); 268 if (old) 269 bpf_task_release(old); 270 } 271 272 bpf_obj_drop(local); 273 return 0; 274 } 275 276 SEC("tp_btf/task_newtask") 277 __failure __msg("Possibly NULL pointer passed to trusted R1") 278 int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags) 279 { 280 struct task_struct *acquired; 281 282 acquired = bpf_task_from_pid(task->pid); 283 284 /* Releasing bpf_task_from_pid() lookup without a NULL check. */ 285 bpf_task_release(acquired); 286 287 return 0; 288 } 289 290 SEC("tp_btf/task_newtask") 291 __failure __msg("Possibly NULL pointer passed to trusted R1") 292 int BPF_PROG(task_kfunc_from_vpid_no_null_check, struct task_struct *task, u64 clone_flags) 293 { 294 struct task_struct *acquired; 295 296 acquired = bpf_task_from_vpid(task->pid); 297 298 /* Releasing bpf_task_from_vpid() lookup without a NULL check. */ 299 bpf_task_release(acquired); 300 301 return 0; 302 } 303 304 SEC("lsm/task_free") 305 __failure __msg("R1 must be a rcu pointer") 306 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task) 307 { 308 struct task_struct *acquired; 309 310 /* the argument of lsm task_free hook is untrusted. */ 311 acquired = bpf_task_acquire(task); 312 if (!acquired) 313 return 0; 314 315 bpf_task_release(acquired); 316 return 0; 317 } 318 319 SEC("tp_btf/task_newtask") 320 __failure __msg("access beyond the end of member comm") 321 int BPF_PROG(task_access_comm1, struct task_struct *task, u64 clone_flags) 322 { 323 bpf_strncmp(task->comm, 17, "foo"); 324 return 0; 325 } 326 327 SEC("tp_btf/task_newtask") 328 __failure __msg("access beyond the end of member comm") 329 int BPF_PROG(task_access_comm2, struct task_struct *task, u64 clone_flags) 330 { 331 bpf_strncmp(task->comm + 1, 16, "foo"); 332 return 0; 333 } 334 335 SEC("tp_btf/task_newtask") 336 __failure __msg("write into memory") 337 int BPF_PROG(task_access_comm3, struct task_struct *task, u64 clone_flags) 338 { 339 bpf_probe_read_kernel(task->comm, 16, task->comm); 340 return 0; 341 } 342 343 SEC("fentry/__set_task_comm") 344 __failure __msg("R1 type=ptr_ expected") 345 int BPF_PROG(task_access_comm4, struct task_struct *task, const char *buf, bool exec) 346 { 347 /* 348 * task->comm is a legacy ptr_to_btf_id. The verifier cannot guarantee 349 * its safety. Hence it cannot be accessed with normal load insns. 350 */ 351 bpf_strncmp(task->comm, 16, "foo"); 352 return 0; 353 } 354 355 SEC("tp_btf/task_newtask") 356 __failure __msg("release kfunc bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1") 357 int BPF_PROG(task_kfunc_release_in_map, struct task_struct *task, u64 clone_flags) 358 { 359 struct task_struct *local; 360 struct __tasks_kfunc_map_value *v; 361 362 if (tasks_kfunc_map_insert(task)) 363 return 0; 364 365 v = tasks_kfunc_map_value_lookup(task); 366 if (!v) 367 return 0; 368 369 bpf_rcu_read_lock(); 370 local = v->task; 371 if (!local) { 372 bpf_rcu_read_unlock(); 373 return 0; 374 } 375 /* Can't release a kptr that's still stored in a map. */ 376 bpf_task_release(local); 377 bpf_rcu_read_unlock(); 378 379 return 0; 380 } 381