selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / exhandler_kern.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021, Oracle and/or its affiliates. */
3
4 #include "vmlinux.h"
5
6 #include <bpf/bpf_helpers.h>
7 #include <bpf/bpf_tracing.h>
8 #include <bpf/bpf_core_read.h>
9
10 char _license[] SEC("license") = "GPL";
11
12 unsigned int exception_triggered;
13 int test_pid;
14
15 /* TRACE_EVENT(task_newtask,
16  *         TP_PROTO(struct task_struct *p, u64 clone_flags)
17  */
18 SEC("tp_btf/task_newtask")
19 int BPF_PROG(trace_task_newtask, struct task_struct *task, u64 clone_flags)
20 {
21         int pid = bpf_get_current_pid_tgid() >> 32;
22         struct callback_head *work;
23         void *func;
24
25         if (test_pid != pid)
26                 return 0;
27
28         /* To verify we hit an exception we dereference task->task_works->func.
29          * If task work has been added,
30          * - task->task_works is non-NULL; and
31          * - task->task_works->func is non-NULL also (the callback function
32          *   must be specified for the task work.
33          *
34          * However, for a newly-created task, task->task_works is NULLed,
35          * so we know the exception handler triggered if task_works is
36          * NULL and func is NULL.
37          */
38         work = task->task_works;
39         func = work->func;
40         /* Currently verifier will fail for `btf_ptr |= btf_ptr` * instruction.
41          * To workaround the issue, use barrier_var() and rewrite as below to
42          * prevent compiler from generating verifier-unfriendly code.
43          */
44         barrier_var(work);
45         if (work)
46                 return 0;
47         barrier_var(func);
48         if (func)
49                 return 0;
50         exception_triggered++;
51         return 0;
52 }