Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2018 Facebook
0003 
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <string.h>
0007 #include <errno.h>
0008 #include <fcntl.h>
0009 #include <syscall.h>
0010 #include <unistd.h>
0011 #include <linux/perf_event.h>
0012 #include <sys/ioctl.h>
0013 #include <sys/time.h>
0014 #include <sys/types.h>
0015 #include <sys/stat.h>
0016 
0017 #include <linux/bpf.h>
0018 #include <bpf/bpf.h>
0019 #include <bpf/libbpf.h>
0020 
0021 #include "cgroup_helpers.h"
0022 #include "testing_helpers.h"
0023 
0024 #define CHECK(condition, tag, format...) ({     \
0025     int __ret = !!(condition);          \
0026     if (__ret) {                    \
0027         printf("%s:FAIL:%s ", __func__, tag);   \
0028         printf(format);             \
0029     } else {                    \
0030         printf("%s:PASS:%s\n", __func__, tag);  \
0031     }                       \
0032     __ret;                      \
0033 })
0034 
0035 static int bpf_find_map(const char *test, struct bpf_object *obj,
0036             const char *name)
0037 {
0038     struct bpf_map *map;
0039 
0040     map = bpf_object__find_map_by_name(obj, name);
0041     if (!map)
0042         return -1;
0043     return bpf_map__fd(map);
0044 }
0045 
0046 #define TEST_CGROUP "/test-bpf-get-cgroup-id/"
0047 
0048 int main(int argc, char **argv)
0049 {
0050     const char *probe_name = "syscalls/sys_enter_nanosleep";
0051     const char *file = "get_cgroup_id_kern.o";
0052     int err, bytes, efd, prog_fd, pmu_fd;
0053     int cgroup_fd, cgidmap_fd, pidmap_fd;
0054     struct perf_event_attr attr = {};
0055     struct bpf_object *obj;
0056     __u64 kcgid = 0, ucgid;
0057     __u32 key = 0, pid;
0058     int exit_code = 1;
0059     char buf[256];
0060     const struct timespec req = {
0061         .tv_sec = 1,
0062         .tv_nsec = 0,
0063     };
0064 
0065     cgroup_fd = cgroup_setup_and_join(TEST_CGROUP);
0066     if (CHECK(cgroup_fd < 0, "cgroup_setup_and_join", "err %d errno %d\n", cgroup_fd, errno))
0067         return 1;
0068 
0069     /* Use libbpf 1.0 API mode */
0070     libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
0071 
0072     err = bpf_prog_test_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
0073     if (CHECK(err, "bpf_prog_test_load", "err %d errno %d\n", err, errno))
0074         goto cleanup_cgroup_env;
0075 
0076     cgidmap_fd = bpf_find_map(__func__, obj, "cg_ids");
0077     if (CHECK(cgidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
0078           cgidmap_fd, errno))
0079         goto close_prog;
0080 
0081     pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
0082     if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
0083           pidmap_fd, errno))
0084         goto close_prog;
0085 
0086     pid = getpid();
0087     bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
0088 
0089     snprintf(buf, sizeof(buf),
0090          "/sys/kernel/debug/tracing/events/%s/id", probe_name);
0091     efd = open(buf, O_RDONLY, 0);
0092     if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
0093         goto close_prog;
0094     bytes = read(efd, buf, sizeof(buf));
0095     close(efd);
0096     if (CHECK(bytes <= 0 || bytes >= sizeof(buf), "read",
0097           "bytes %d errno %d\n", bytes, errno))
0098         goto close_prog;
0099 
0100     attr.config = strtol(buf, NULL, 0);
0101     attr.type = PERF_TYPE_TRACEPOINT;
0102     attr.sample_type = PERF_SAMPLE_RAW;
0103     attr.sample_period = 1;
0104     attr.wakeup_events = 1;
0105 
0106     /* attach to this pid so the all bpf invocations will be in the
0107      * cgroup associated with this pid.
0108      */
0109     pmu_fd = syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
0110     if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd,
0111           errno))
0112         goto close_prog;
0113 
0114     err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
0115     if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", err,
0116           errno))
0117         goto close_pmu;
0118 
0119     err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
0120     if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", err,
0121           errno))
0122         goto close_pmu;
0123 
0124     /* trigger some syscalls */
0125     syscall(__NR_nanosleep, &req, NULL);
0126 
0127     err = bpf_map_lookup_elem(cgidmap_fd, &key, &kcgid);
0128     if (CHECK(err, "bpf_map_lookup_elem", "err %d errno %d\n", err, errno))
0129         goto close_pmu;
0130 
0131     ucgid = get_cgroup_id(TEST_CGROUP);
0132     if (CHECK(kcgid != ucgid, "compare_cgroup_id",
0133           "kern cgid %llx user cgid %llx", kcgid, ucgid))
0134         goto close_pmu;
0135 
0136     exit_code = 0;
0137     printf("%s:PASS\n", argv[0]);
0138 
0139 close_pmu:
0140     close(pmu_fd);
0141 close_prog:
0142     bpf_object__close(obj);
0143 cleanup_cgroup_env:
0144     cleanup_cgroup_environment();
0145     return exit_code;
0146 }