Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (c) 2017 Facebook
0003  */
0004 #include <stdio.h>
0005 #include <unistd.h>
0006 #include <fcntl.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009 #include <linux/perf_event.h>
0010 #include <errno.h>
0011 #include <bpf/libbpf.h>
0012 #include <bpf/bpf.h>
0013 
0014 /* This program verifies bpf attachment to tracepoint sys_enter_* and sys_exit_*.
0015  * This requires kernel CONFIG_FTRACE_SYSCALLS to be set.
0016  */
0017 
0018 static void usage(const char *cmd)
0019 {
0020     printf("USAGE: %s [-i num_progs] [-h]\n", cmd);
0021     printf("       -i num_progs      # number of progs of the test\n");
0022     printf("       -h                # help\n");
0023 }
0024 
0025 static void verify_map(int map_id)
0026 {
0027     __u32 key = 0;
0028     __u32 val;
0029 
0030     if (bpf_map_lookup_elem(map_id, &key, &val) != 0) {
0031         fprintf(stderr, "map_lookup failed: %s\n", strerror(errno));
0032         return;
0033     }
0034     if (val == 0) {
0035         fprintf(stderr, "failed: map #%d returns value 0\n", map_id);
0036         return;
0037     }
0038 
0039     printf("verify map:%d val: %d\n", map_id, val);
0040 
0041     val = 0;
0042     if (bpf_map_update_elem(map_id, &key, &val, BPF_ANY) != 0) {
0043         fprintf(stderr, "map_update failed: %s\n", strerror(errno));
0044         return;
0045     }
0046 }
0047 
0048 static int test(char *filename, int num_progs)
0049 {
0050     int map0_fds[num_progs], map1_fds[num_progs], fd, i, j = 0;
0051     struct bpf_link *links[num_progs * 4];
0052     struct bpf_object *objs[num_progs];
0053     struct bpf_program *prog;
0054 
0055     for (i = 0; i < num_progs; i++) {
0056         objs[i] = bpf_object__open_file(filename, NULL);
0057         if (libbpf_get_error(objs[i])) {
0058             fprintf(stderr, "opening BPF object file failed\n");
0059             objs[i] = NULL;
0060             goto cleanup;
0061         }
0062 
0063         /* load BPF program */
0064         if (bpf_object__load(objs[i])) {
0065             fprintf(stderr, "loading BPF object file failed\n");
0066             goto cleanup;
0067         }
0068 
0069         map0_fds[i] = bpf_object__find_map_fd_by_name(objs[i],
0070                                   "enter_open_map");
0071         map1_fds[i] = bpf_object__find_map_fd_by_name(objs[i],
0072                                   "exit_open_map");
0073         if (map0_fds[i] < 0 || map1_fds[i] < 0) {
0074             fprintf(stderr, "finding a map in obj file failed\n");
0075             goto cleanup;
0076         }
0077 
0078         bpf_object__for_each_program(prog, objs[i]) {
0079             links[j] = bpf_program__attach(prog);
0080             if (libbpf_get_error(links[j])) {
0081                 fprintf(stderr, "bpf_program__attach failed\n");
0082                 links[j] = NULL;
0083                 goto cleanup;
0084             }
0085             j++;
0086         }
0087         printf("prog #%d: map ids %d %d\n", i, map0_fds[i], map1_fds[i]);
0088     }
0089 
0090     /* current load_bpf_file has perf_event_open default pid = -1
0091      * and cpu = 0, which permits attached bpf execution on
0092      * all cpus for all pid's. bpf program execution ignores
0093      * cpu affinity.
0094      */
0095     /* trigger some "open" operations */
0096     fd = open(filename, O_RDONLY);
0097     if (fd < 0) {
0098         fprintf(stderr, "open failed: %s\n", strerror(errno));
0099         return 1;
0100     }
0101     close(fd);
0102 
0103     /* verify the map */
0104     for (i = 0; i < num_progs; i++) {
0105         verify_map(map0_fds[i]);
0106         verify_map(map1_fds[i]);
0107     }
0108 
0109 cleanup:
0110     for (j--; j >= 0; j--)
0111         bpf_link__destroy(links[j]);
0112 
0113     for (i--; i >= 0; i--)
0114         bpf_object__close(objs[i]);
0115     return 0;
0116 }
0117 
0118 int main(int argc, char **argv)
0119 {
0120     int opt, num_progs = 1;
0121     char filename[256];
0122 
0123     while ((opt = getopt(argc, argv, "i:h")) != -1) {
0124         switch (opt) {
0125         case 'i':
0126             num_progs = atoi(optarg);
0127             break;
0128         case 'h':
0129         default:
0130             usage(argv[0]);
0131             return 0;
0132         }
0133     }
0134 
0135     snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
0136 
0137     return test(filename, num_progs);
0138 }