Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <errno.h>
8#include <fcntl.h>
9#include <syscall.h>
10#include <unistd.h>
11#include <linux/perf_event.h>
12#include <sys/ioctl.h>
13#include <sys/time.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16
17#include <linux/bpf.h>
18#include <bpf/bpf.h>
19#include <bpf/libbpf.h>
20
21#include "cgroup_helpers.h"
22#include "testing_helpers.h"
23#include "bpf_rlimit.h"
24
25#define CHECK(condition, tag, format...) ({ \
26 int __ret = !!(condition); \
27 if (__ret) { \
28 printf("%s:FAIL:%s ", __func__, tag); \
29 printf(format); \
30 } else { \
31 printf("%s:PASS:%s\n", __func__, tag); \
32 } \
33 __ret; \
34})
35
36static int bpf_find_map(const char *test, struct bpf_object *obj,
37 const char *name)
38{
39 struct bpf_map *map;
40
41 map = bpf_object__find_map_by_name(obj, name);
42 if (!map)
43 return -1;
44 return bpf_map__fd(map);
45}
46
47#define TEST_CGROUP "/test-bpf-get-cgroup-id/"
48
49int main(int argc, char **argv)
50{
51 const char *probe_name = "syscalls/sys_enter_nanosleep";
52 const char *file = "get_cgroup_id_kern.o";
53 int err, bytes, efd, prog_fd, pmu_fd;
54 int cgroup_fd, cgidmap_fd, pidmap_fd;
55 struct perf_event_attr attr = {};
56 struct bpf_object *obj;
57 __u64 kcgid = 0, ucgid;
58 __u32 key = 0, pid;
59 int exit_code = 1;
60 char buf[256];
61 const struct timespec req = {
62 .tv_sec = 1,
63 .tv_nsec = 0,
64 };
65
66 cgroup_fd = cgroup_setup_and_join(TEST_CGROUP);
67 if (CHECK(cgroup_fd < 0, "cgroup_setup_and_join", "err %d errno %d\n", cgroup_fd, errno))
68 return 1;
69
70 err = bpf_prog_test_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
71 if (CHECK(err, "bpf_prog_test_load", "err %d errno %d\n", err, errno))
72 goto cleanup_cgroup_env;
73
74 cgidmap_fd = bpf_find_map(__func__, obj, "cg_ids");
75 if (CHECK(cgidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
76 cgidmap_fd, errno))
77 goto close_prog;
78
79 pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
80 if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
81 pidmap_fd, errno))
82 goto close_prog;
83
84 pid = getpid();
85 bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
86
87 snprintf(buf, sizeof(buf),
88 "/sys/kernel/debug/tracing/events/%s/id", probe_name);
89 efd = open(buf, O_RDONLY, 0);
90 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
91 goto close_prog;
92 bytes = read(efd, buf, sizeof(buf));
93 close(efd);
94 if (CHECK(bytes <= 0 || bytes >= sizeof(buf), "read",
95 "bytes %d errno %d\n", bytes, errno))
96 goto close_prog;
97
98 attr.config = strtol(buf, NULL, 0);
99 attr.type = PERF_TYPE_TRACEPOINT;
100 attr.sample_type = PERF_SAMPLE_RAW;
101 attr.sample_period = 1;
102 attr.wakeup_events = 1;
103
104 /* attach to this pid so the all bpf invocations will be in the
105 * cgroup associated with this pid.
106 */
107 pmu_fd = syscall(__NR_perf_event_open, &attr, getpid(), -1, -1, 0);
108 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd,
109 errno))
110 goto close_prog;
111
112 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
113 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n", err,
114 errno))
115 goto close_pmu;
116
117 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
118 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n", err,
119 errno))
120 goto close_pmu;
121
122 /* trigger some syscalls */
123 syscall(__NR_nanosleep, &req, NULL);
124
125 err = bpf_map_lookup_elem(cgidmap_fd, &key, &kcgid);
126 if (CHECK(err, "bpf_map_lookup_elem", "err %d errno %d\n", err, errno))
127 goto close_pmu;
128
129 ucgid = get_cgroup_id(TEST_CGROUP);
130 if (CHECK(kcgid != ucgid, "compare_cgroup_id",
131 "kern cgid %llx user cgid %llx", kcgid, ucgid))
132 goto close_pmu;
133
134 exit_code = 0;
135 printf("%s:PASS\n", argv[0]);
136
137close_pmu:
138 close(pmu_fd);
139close_prog:
140 bpf_object__close(obj);
141cleanup_cgroup_env:
142 cleanup_cgroup_environment();
143 return exit_code;
144}