linux/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#define _GNU_SOURCE
   3#include <pthread.h>
   4#include <sched.h>
   5#include <sys/socket.h>
   6#include <test_progs.h>
   7
   8#define MAX_CNT_RAWTP   10ull
   9#define MAX_STACK_RAWTP 100
  10
  11static int duration = 0;
  12
  13struct get_stack_trace_t {
  14        int pid;
  15        int kern_stack_size;
  16        int user_stack_size;
  17        int user_stack_buildid_size;
  18        __u64 kern_stack[MAX_STACK_RAWTP];
  19        __u64 user_stack[MAX_STACK_RAWTP];
  20        struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP];
  21};
  22
  23static void get_stack_print_output(void *ctx, int cpu, void *data, __u32 size)
  24{
  25        bool good_kern_stack = false, good_user_stack = false;
  26        const char *nonjit_func = "___bpf_prog_run";
  27        struct get_stack_trace_t *e = data;
  28        int i, num_stack;
  29        static __u64 cnt;
  30        struct ksym *ks;
  31
  32        cnt++;
  33
  34        if (size < sizeof(struct get_stack_trace_t)) {
  35                __u64 *raw_data = data;
  36                bool found = false;
  37
  38                num_stack = size / sizeof(__u64);
  39                /* If jit is enabled, we do not have a good way to
  40                 * verify the sanity of the kernel stack. So we
  41                 * just assume it is good if the stack is not empty.
  42                 * This could be improved in the future.
  43                 */
  44                if (env.jit_enabled) {
  45                        found = num_stack > 0;
  46                } else {
  47                        for (i = 0; i < num_stack; i++) {
  48                                ks = ksym_search(raw_data[i]);
  49                                if (ks && (strcmp(ks->name, nonjit_func) == 0)) {
  50                                        found = true;
  51                                        break;
  52                                }
  53                        }
  54                }
  55                if (found) {
  56                        good_kern_stack = true;
  57                        good_user_stack = true;
  58                }
  59        } else {
  60                num_stack = e->kern_stack_size / sizeof(__u64);
  61                if (env.jit_enabled) {
  62                        good_kern_stack = num_stack > 0;
  63                } else {
  64                        for (i = 0; i < num_stack; i++) {
  65                                ks = ksym_search(e->kern_stack[i]);
  66                                if (ks && (strcmp(ks->name, nonjit_func) == 0)) {
  67                                        good_kern_stack = true;
  68                                        break;
  69                                }
  70                        }
  71                }
  72                if (e->user_stack_size > 0 && e->user_stack_buildid_size > 0)
  73                        good_user_stack = true;
  74        }
  75
  76        if (!good_kern_stack)
  77            CHECK(!good_kern_stack, "kern_stack", "corrupted kernel stack\n");
  78        if (!good_user_stack)
  79            CHECK(!good_user_stack, "user_stack", "corrupted user stack\n");
  80}
  81
  82void test_get_stack_raw_tp(void)
  83{
  84        const char *file = "./test_get_stack_rawtp.o";
  85        const char *file_err = "./test_get_stack_rawtp_err.o";
  86        const char *prog_name = "raw_tracepoint/sys_enter";
  87        int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;
  88        struct perf_buffer_opts pb_opts = {};
  89        struct perf_buffer *pb = NULL;
  90        struct bpf_link *link = NULL;
  91        struct timespec tv = {0, 10};
  92        struct bpf_program *prog;
  93        struct bpf_object *obj;
  94        struct bpf_map *map;
  95        cpu_set_t cpu_set;
  96
  97        err = bpf_prog_load(file_err, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
  98        if (CHECK(err >= 0, "prog_load raw tp", "err %d errno %d\n", err, errno))
  99                return;
 100
 101        err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
 102        if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
 103                return;
 104
 105        prog = bpf_object__find_program_by_title(obj, prog_name);
 106        if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))
 107                goto close_prog;
 108
 109        map = bpf_object__find_map_by_name(obj, "perfmap");
 110        if (CHECK(!map, "bpf_find_map", "not found\n"))
 111                goto close_prog;
 112
 113        err = load_kallsyms();
 114        if (CHECK(err < 0, "load_kallsyms", "err %d errno %d\n", err, errno))
 115                goto close_prog;
 116
 117        CPU_ZERO(&cpu_set);
 118        CPU_SET(0, &cpu_set);
 119        err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
 120        if (CHECK(err, "set_affinity", "err %d, errno %d\n", err, errno))
 121                goto close_prog;
 122
 123        link = bpf_program__attach_raw_tracepoint(prog, "sys_enter");
 124        if (!ASSERT_OK_PTR(link, "attach_raw_tp"))
 125                goto close_prog;
 126
 127        pb_opts.sample_cb = get_stack_print_output;
 128        pb = perf_buffer__new(bpf_map__fd(map), 8, &pb_opts);
 129        if (!ASSERT_OK_PTR(pb, "perf_buf__new"))
 130                goto close_prog;
 131
 132        /* trigger some syscall action */
 133        for (i = 0; i < MAX_CNT_RAWTP; i++)
 134                nanosleep(&tv, NULL);
 135
 136        while (exp_cnt > 0) {
 137                err = perf_buffer__poll(pb, 100);
 138                if (err < 0 && CHECK(err < 0, "pb__poll", "err %d\n", err))
 139                        goto close_prog;
 140                exp_cnt -= err;
 141        }
 142
 143close_prog:
 144        bpf_link__destroy(link);
 145        perf_buffer__free(pb);
 146        bpf_object__close(obj);
 147}
 148