]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-process-util.c
Merge pull request #3749 from phomes/trivial-fixes3
[thirdparty/systemd.git] / src / test / test-process-util.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Thomas H.P. Andersen
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <sched.h>
22 #include <sys/mount.h>
23 #include <sys/personality.h>
24 #include <sys/prctl.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <unistd.h>
29 #ifdef HAVE_VALGRIND_VALGRIND_H
30 #include <valgrind/valgrind.h>
31 #endif
32
33 #include "alloc-util.h"
34 #include "architecture.h"
35 #include "fd-util.h"
36 #include "log.h"
37 #include "macro.h"
38 #include "parse-util.h"
39 #include "process-util.h"
40 #include "stdio-util.h"
41 #include "string-util.h"
42 #include "terminal-util.h"
43 #include "util.h"
44 #include "virt.h"
45
46 static void test_get_process_comm(pid_t pid) {
47 struct stat st;
48 _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
49 _cleanup_free_ char *env = NULL;
50 char path[strlen("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
51 pid_t e;
52 uid_t u;
53 gid_t g;
54 dev_t h;
55 int r;
56
57 xsprintf(path, "/proc/"PID_FMT"/comm", pid);
58
59 if (stat(path, &st) == 0) {
60 assert_se(get_process_comm(pid, &a) >= 0);
61 log_info("PID"PID_FMT" comm: '%s'", pid, a);
62 } else
63 log_warning("%s not exist.", path);
64
65 assert_se(get_process_cmdline(pid, 0, true, &c) >= 0);
66 log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
67
68 assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
69 log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
70
71 free(d);
72 assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
73 log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
74
75 assert_se(get_process_ppid(pid, &e) >= 0);
76 log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
77 assert_se(pid == 1 ? e == 0 : e > 0);
78
79 assert_se(is_kernel_thread(pid) == 0 || pid != 1);
80
81 r = get_process_exe(pid, &f);
82 assert_se(r >= 0 || r == -EACCES);
83 log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
84
85 assert_se(get_process_uid(pid, &u) == 0);
86 log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
87 assert_se(u == 0 || pid != 1);
88
89 assert_se(get_process_gid(pid, &g) == 0);
90 log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
91 assert_se(g == 0 || pid != 1);
92
93 r = get_process_environ(pid, &env);
94 assert_se(r >= 0 || r == -EACCES);
95 log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
96
97 if (!detect_container())
98 assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
99
100 getenv_for_pid(pid, "PATH", &i);
101 log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
102 }
103
104 static void test_pid_is_unwaited(void) {
105 pid_t pid;
106
107 pid = fork();
108 assert_se(pid >= 0);
109 if (pid == 0) {
110 _exit(EXIT_SUCCESS);
111 } else {
112 int status;
113
114 waitpid(pid, &status, 0);
115 assert_se(!pid_is_unwaited(pid));
116 }
117 assert_se(pid_is_unwaited(getpid()));
118 assert_se(!pid_is_unwaited(-1));
119 }
120
121 static void test_pid_is_alive(void) {
122 pid_t pid;
123
124 pid = fork();
125 assert_se(pid >= 0);
126 if (pid == 0) {
127 _exit(EXIT_SUCCESS);
128 } else {
129 int status;
130
131 waitpid(pid, &status, 0);
132 assert_se(!pid_is_alive(pid));
133 }
134 assert_se(pid_is_alive(getpid()));
135 assert_se(!pid_is_alive(-1));
136 }
137
138 static void test_personality(void) {
139
140 assert_se(personality_to_string(PER_LINUX));
141 assert_se(!personality_to_string(PERSONALITY_INVALID));
142
143 assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
144
145 assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
146 assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
147
148 #ifdef __x86_64__
149 assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
150 assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
151
152 assert_se(personality_from_string("x86-64") == PER_LINUX);
153 assert_se(personality_from_string("x86") == PER_LINUX32);
154 assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
155 assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
156
157 assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
158 #endif
159 }
160
161 static void test_get_process_cmdline_harder(void) {
162 char path[] = "/tmp/test-cmdlineXXXXXX";
163 _cleanup_close_ int fd = -1;
164 _cleanup_free_ char *line = NULL;
165 pid_t pid;
166
167 if (geteuid() != 0)
168 return;
169
170 #ifdef HAVE_VALGRIND_VALGRIND_H
171 /* valgrind patches open(/proc//cmdline)
172 * so, test_get_process_cmdline_harder fails always
173 * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
174 if (RUNNING_ON_VALGRIND)
175 return;
176 #endif
177
178 pid = fork();
179 if (pid > 0) {
180 siginfo_t si;
181
182 (void) wait_for_terminate(pid, &si);
183
184 assert_se(si.si_code == CLD_EXITED);
185 assert_se(si.si_status == 0);
186
187 return;
188 }
189
190 assert_se(pid == 0);
191 assert_se(unshare(CLONE_NEWNS) >= 0);
192
193 fd = mkostemp(path, O_CLOEXEC);
194 assert_se(fd >= 0);
195 assert_se(mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) >= 0);
196 assert_se(unlink(path) >= 0);
197
198 assert_se(prctl(PR_SET_NAME, "testa") >= 0);
199
200 assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
201
202 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
203 assert_se(streq(line, "[testa]"));
204 line = mfree(line);
205
206 assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
207 assert_se(streq(line, ""));
208 line = mfree(line);
209
210 assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
211 assert_se(streq(line, "["));
212 line = mfree(line);
213
214 assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
215 assert_se(streq(line, "[."));
216 line = mfree(line);
217
218 assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
219 assert_se(streq(line, "[.."));
220 line = mfree(line);
221
222 assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
223 assert_se(streq(line, "[..."));
224 line = mfree(line);
225
226 assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
227 assert_se(streq(line, "[...]"));
228 line = mfree(line);
229
230 assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
231 assert_se(streq(line, "[t...]"));
232 line = mfree(line);
233
234 assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
235 assert_se(streq(line, "[testa]"));
236 line = mfree(line);
237
238 assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
239
240 assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
241
242 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
243 assert_se(streq(line, "[testa]"));
244 line = mfree(line);
245
246 assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
247
248 assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
249 assert_se(streq(line, "foo bar"));
250 line = mfree(line);
251
252 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
253 assert_se(streq(line, "foo bar"));
254 line = mfree(line);
255
256 assert_se(write(fd, "quux", 4) == 4);
257 assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
258 assert_se(streq(line, "foo bar quux"));
259 line = mfree(line);
260
261 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
262 assert_se(streq(line, "foo bar quux"));
263 line = mfree(line);
264
265 assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
266 assert_se(streq(line, ""));
267 line = mfree(line);
268
269 assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
270 assert_se(streq(line, "."));
271 line = mfree(line);
272
273 assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
274 assert_se(streq(line, ".."));
275 line = mfree(line);
276
277 assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
278 assert_se(streq(line, "..."));
279 line = mfree(line);
280
281 assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
282 assert_se(streq(line, "f..."));
283 line = mfree(line);
284
285 assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
286 assert_se(streq(line, "fo..."));
287 line = mfree(line);
288
289 assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
290 assert_se(streq(line, "foo..."));
291 line = mfree(line);
292
293 assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
294 assert_se(streq(line, "foo..."));
295 line = mfree(line);
296
297 assert_se(get_process_cmdline(getpid(), 9, true, &line) >= 0);
298 assert_se(streq(line, "foo b..."));
299 line = mfree(line);
300
301 assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
302 assert_se(streq(line, "foo ba..."));
303 line = mfree(line);
304
305 assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
306 assert_se(streq(line, "foo bar..."));
307 line = mfree(line);
308
309 assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
310 assert_se(streq(line, "foo bar..."));
311 line = mfree(line);
312
313 assert_se(get_process_cmdline(getpid(), 13, true, &line) >= 0);
314 assert_se(streq(line, "foo bar quux"));
315 line = mfree(line);
316
317 assert_se(get_process_cmdline(getpid(), 14, true, &line) >= 0);
318 assert_se(streq(line, "foo bar quux"));
319 line = mfree(line);
320
321 assert_se(get_process_cmdline(getpid(), 1000, true, &line) >= 0);
322 assert_se(streq(line, "foo bar quux"));
323 line = mfree(line);
324
325 assert_se(ftruncate(fd, 0) >= 0);
326 assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
327
328 assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
329
330 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
331 assert_se(streq(line, "[aaaa bbbb cccc]"));
332 line = mfree(line);
333
334 assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
335 assert_se(streq(line, "[aaaa...]"));
336 line = mfree(line);
337
338 assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
339 assert_se(streq(line, "[aaaa...]"));
340 line = mfree(line);
341
342 assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
343 assert_se(streq(line, "[aaaa b...]"));
344 line = mfree(line);
345
346 safe_close(fd);
347 _exit(0);
348 }
349
350 int main(int argc, char *argv[]) {
351 log_parse_environment();
352 log_open();
353
354 if (argc > 1) {
355 pid_t pid = 0;
356
357 (void) parse_pid(argv[1], &pid);
358 test_get_process_comm(pid);
359 } else {
360 test_get_process_comm(1);
361 test_get_process_comm(getpid());
362 }
363
364 test_pid_is_unwaited();
365 test_pid_is_alive();
366 test_personality();
367 test_get_process_cmdline_harder();
368
369 return 0;
370 }