]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-namespace.c
7571e609a26fe8236a4c691881b00a9a6c91a9ca
[thirdparty/systemd.git] / src / test / test-namespace.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <fcntl.h>
4 #include <sys/socket.h>
5 #include <sys/stat.h>
6
7 #include "alloc-util.h"
8 #include "fd-util.h"
9 #include "namespace.h"
10 #include "process-util.h"
11 #include "string-util.h"
12 #include "tests.h"
13 #include "user-util.h"
14 #include "util.h"
15 #include "virt.h"
16
17 static void test_namespace_cleanup_tmpdir(void) {
18 {
19 _cleanup_(namespace_cleanup_tmpdirp) char *dir;
20 assert_se(dir = strdup(RUN_SYSTEMD_EMPTY));
21 }
22
23 {
24 _cleanup_(namespace_cleanup_tmpdirp) char *dir;
25 assert_se(dir = strdup("/tmp/systemd-test-namespace.XXXXXX"));
26 assert_se(mkdtemp(dir));
27 }
28 }
29
30 static void test_tmpdir(const char *id, const char *A, const char *B) {
31 _cleanup_free_ char *a, *b;
32 struct stat x, y;
33 char *c, *d;
34
35 assert_se(setup_tmp_dirs(id, &a, &b) == 0);
36
37 assert_se(stat(a, &x) >= 0);
38 assert_se(stat(b, &y) >= 0);
39
40 assert_se(S_ISDIR(x.st_mode));
41 assert_se(S_ISDIR(y.st_mode));
42
43 if (!streq(a, RUN_SYSTEMD_EMPTY)) {
44 assert_se(startswith(a, A));
45 assert_se((x.st_mode & 01777) == 0700);
46 c = strjoina(a, "/tmp");
47 assert_se(stat(c, &x) >= 0);
48 assert_se(S_ISDIR(x.st_mode));
49 assert_se(FLAGS_SET(x.st_mode, 01777));
50 assert_se(rmdir(c) >= 0);
51 assert_se(rmdir(a) >= 0);
52 }
53
54 if (!streq(b, RUN_SYSTEMD_EMPTY)) {
55 assert_se(startswith(b, B));
56 assert_se((y.st_mode & 01777) == 0700);
57 d = strjoina(b, "/tmp");
58 assert_se(stat(d, &y) >= 0);
59 assert_se(S_ISDIR(y.st_mode));
60 assert_se(FLAGS_SET(y.st_mode, 01777));
61 assert_se(rmdir(d) >= 0);
62 assert_se(rmdir(b) >= 0);
63 }
64 }
65
66 static void test_netns(void) {
67 _cleanup_close_pair_ int s[2] = { -1, -1 };
68 pid_t pid1, pid2, pid3;
69 int r, n = 0;
70 siginfo_t si;
71
72 if (geteuid() > 0) {
73 (void) log_tests_skipped("not root");
74 return;
75 }
76
77 assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0);
78
79 pid1 = fork();
80 assert_se(pid1 >= 0);
81
82 if (pid1 == 0) {
83 r = setup_netns(s);
84 assert_se(r >= 0);
85 _exit(r);
86 }
87
88 pid2 = fork();
89 assert_se(pid2 >= 0);
90
91 if (pid2 == 0) {
92 r = setup_netns(s);
93 assert_se(r >= 0);
94 exit(r);
95 }
96
97 pid3 = fork();
98 assert_se(pid3 >= 0);
99
100 if (pid3 == 0) {
101 r = setup_netns(s);
102 assert_se(r >= 0);
103 exit(r);
104 }
105
106 r = wait_for_terminate(pid1, &si);
107 assert_se(r >= 0);
108 assert_se(si.si_code == CLD_EXITED);
109 n += si.si_status;
110
111 r = wait_for_terminate(pid2, &si);
112 assert_se(r >= 0);
113 assert_se(si.si_code == CLD_EXITED);
114 n += si.si_status;
115
116 r = wait_for_terminate(pid3, &si);
117 assert_se(r >= 0);
118 assert_se(si.si_code == CLD_EXITED);
119 n += si.si_status;
120
121 assert_se(n == 1);
122 }
123
124 static void test_protect_kernel_logs(void) {
125 int r;
126 pid_t pid;
127 static const NamespaceInfo ns_info = {
128 .protect_kernel_logs = true,
129 };
130
131 if (geteuid() > 0) {
132 (void) log_tests_skipped("not root");
133 return;
134 }
135
136 /* In a container we likely don't have access to /dev/kmsg */
137 if (detect_container() > 0) {
138 (void) log_tests_skipped("in container");
139 return;
140 }
141
142
143 pid = fork();
144 assert_se(pid >= 0);
145
146 if (pid == 0) {
147 _cleanup_close_ int fd = -1;
148
149 fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC);
150 assert_se(fd > 0);
151
152 r = setup_namespace(NULL,
153 NULL,
154 NULL,
155 &ns_info,
156 NULL,
157 NULL,
158 NULL,
159 NULL,
160 NULL, 0,
161 NULL, 0,
162 NULL, 0,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 0,
168 NULL,
169 0,
170 NULL,
171 NULL,
172 0,
173 NULL,
174 NULL,
175 0,
176 NULL);
177 assert_se(r == 0);
178
179 assert_se(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) >= 0);
180 assert_se(open("/dev/kmsg", O_RDONLY | O_CLOEXEC) < 0);
181 assert_se(errno == EACCES);
182
183 _exit(EXIT_SUCCESS);
184 }
185
186 assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS);
187 }
188
189 int main(int argc, char *argv[]) {
190 sd_id128_t bid;
191 char boot_id[SD_ID128_STRING_MAX];
192 _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL;
193
194 test_setup_logging(LOG_INFO);
195
196 test_namespace_cleanup_tmpdir();
197
198 if (!have_namespaces()) {
199 log_tests_skipped("Don't have namespace support");
200 return EXIT_TEST_SKIP;
201 }
202
203 assert_se(sd_id128_get_boot(&bid) >= 0);
204 sd_id128_to_string(bid, boot_id);
205
206 x = strjoin("/tmp/systemd-private-", boot_id, "-abcd.service-");
207 y = strjoin("/var/tmp/systemd-private-", boot_id, "-abcd.service-");
208 assert_se(x && y);
209
210 test_tmpdir("abcd.service", x, y);
211
212 z = strjoin("/tmp/systemd-private-", boot_id, "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
213 zz = strjoin("/var/tmp/systemd-private-", boot_id, "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
214
215 assert_se(z && zz);
216
217 test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
218
219 test_netns();
220 test_protect_kernel_logs();
221
222 return EXIT_SUCCESS;
223 }