2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Thomas H.P. Andersen
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.
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.
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/>.
22 #include <sys/mount.h>
23 #include <sys/personality.h>
24 #include <sys/prctl.h>
26 #include <sys/types.h>
29 #ifdef HAVE_VALGRIND_VALGRIND_H
30 #include <valgrind/valgrind.h>
33 #include "alloc-util.h"
34 //#include "architecture.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 "test-helper.h"
47 static void test_get_process_comm(pid_t pid) {
49 _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
50 _cleanup_free_ char *env = NULL;
51 char path[strlen("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
52 #if 0 /// UNNEEDED by elogind
60 xsprintf(path, "/proc/"PID_FMT"/comm", pid);
62 if (stat(path, &st) == 0) {
63 assert_se(get_process_comm(pid, &a) >= 0);
64 log_info("PID"PID_FMT" comm: '%s'", pid, a);
66 log_warning("%s not exist.", path);
68 assert_se(get_process_cmdline(pid, 0, true, &c) >= 0);
69 log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
71 assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
72 log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
75 assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
76 log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
78 #if 0 /// UNNEEDED by elogind
79 assert_se(get_process_ppid(pid, &e) >= 0);
80 log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
81 assert_se(pid == 1 ? e == 0 : e > 0);
84 assert_se(is_kernel_thread(pid) == 0 || pid != 1);
86 r = get_process_exe(pid, &f);
87 assert_se(r >= 0 || r == -EACCES);
88 log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
90 #if 0 /// UNNEEDED by elogind
91 assert_se(get_process_uid(pid, &u) == 0);
92 log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
93 assert_se(u == 0 || pid != 1);
95 assert_se(get_process_gid(pid, &g) == 0);
96 log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
97 assert_se(g == 0 || pid != 1);
99 r = get_process_environ(pid, &env);
100 assert_se(r >= 0 || r == -EACCES);
101 log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
104 if (!detect_container())
105 assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
107 getenv_for_pid(pid, "PATH", &i);
108 log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
111 static void test_pid_is_unwaited(void) {
121 waitpid(pid, &status, 0);
122 assert_se(!pid_is_unwaited(pid));
124 assert_se(pid_is_unwaited(getpid()));
125 assert_se(!pid_is_unwaited(-1));
128 static void test_pid_is_alive(void) {
138 waitpid(pid, &status, 0);
139 assert_se(!pid_is_alive(pid));
141 assert_se(pid_is_alive(getpid()));
142 assert_se(!pid_is_alive(-1));
145 #if 0 /// UNNEEDED by elogind
146 static void test_personality(void) {
148 assert_se(personality_to_string(PER_LINUX));
149 assert_se(!personality_to_string(PERSONALITY_INVALID));
151 assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
153 assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
154 assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
157 assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
158 assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
160 assert_se(personality_from_string("x86-64") == PER_LINUX);
161 assert_se(personality_from_string("x86") == PER_LINUX32);
162 assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
163 assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
165 assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
170 static void test_get_process_cmdline_harder(void) {
171 char path[] = "/tmp/test-cmdlineXXXXXX";
172 _cleanup_close_ int fd = -1;
173 _cleanup_free_ char *line = NULL;
179 #ifdef HAVE_VALGRIND_VALGRIND_H
180 /* valgrind patches open(/proc//cmdline)
181 * so, test_get_process_cmdline_harder fails always
182 * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
183 if (RUNNING_ON_VALGRIND)
191 (void) wait_for_terminate(pid, &si);
193 assert_se(si.si_code == CLD_EXITED);
194 assert_se(si.si_status == 0);
200 assert_se(unshare(CLONE_NEWNS) >= 0);
202 fd = mkostemp(path, O_CLOEXEC);
205 if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
206 /* This happens under selinux… Abort the test in this case. */
207 log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
208 assert(errno == EACCES);
212 assert_se(unlink(path) >= 0);
214 assert_se(prctl(PR_SET_NAME, "testa") >= 0);
216 assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
218 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
219 assert_se(streq(line, "[testa]"));
222 assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
223 assert_se(streq(line, ""));
226 assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
227 assert_se(streq(line, "["));
230 assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
231 assert_se(streq(line, "[."));
234 assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
235 assert_se(streq(line, "[.."));
238 assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
239 assert_se(streq(line, "[..."));
242 assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
243 assert_se(streq(line, "[...]"));
246 assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
247 assert_se(streq(line, "[t...]"));
250 assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
251 assert_se(streq(line, "[testa]"));
254 assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
256 assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
258 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
259 assert_se(streq(line, "[testa]"));
262 assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
264 assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
265 assert_se(streq(line, "foo bar"));
268 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
269 assert_se(streq(line, "foo bar"));
272 assert_se(write(fd, "quux", 4) == 4);
273 assert_se(get_process_cmdline(getpid(), 0, false, &line) >= 0);
274 assert_se(streq(line, "foo bar quux"));
277 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
278 assert_se(streq(line, "foo bar quux"));
281 assert_se(get_process_cmdline(getpid(), 1, true, &line) >= 0);
282 assert_se(streq(line, ""));
285 assert_se(get_process_cmdline(getpid(), 2, true, &line) >= 0);
286 assert_se(streq(line, "."));
289 assert_se(get_process_cmdline(getpid(), 3, true, &line) >= 0);
290 assert_se(streq(line, ".."));
293 assert_se(get_process_cmdline(getpid(), 4, true, &line) >= 0);
294 assert_se(streq(line, "..."));
297 assert_se(get_process_cmdline(getpid(), 5, true, &line) >= 0);
298 assert_se(streq(line, "f..."));
301 assert_se(get_process_cmdline(getpid(), 6, true, &line) >= 0);
302 assert_se(streq(line, "fo..."));
305 assert_se(get_process_cmdline(getpid(), 7, true, &line) >= 0);
306 assert_se(streq(line, "foo..."));
309 assert_se(get_process_cmdline(getpid(), 8, true, &line) >= 0);
310 assert_se(streq(line, "foo..."));
313 assert_se(get_process_cmdline(getpid(), 9, true, &line) >= 0);
314 assert_se(streq(line, "foo b..."));
317 assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
318 assert_se(streq(line, "foo ba..."));
321 assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
322 assert_se(streq(line, "foo bar..."));
325 assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
326 assert_se(streq(line, "foo bar..."));
329 assert_se(get_process_cmdline(getpid(), 13, true, &line) >= 0);
330 assert_se(streq(line, "foo bar quux"));
333 assert_se(get_process_cmdline(getpid(), 14, true, &line) >= 0);
334 assert_se(streq(line, "foo bar quux"));
337 assert_se(get_process_cmdline(getpid(), 1000, true, &line) >= 0);
338 assert_se(streq(line, "foo bar quux"));
341 assert_se(ftruncate(fd, 0) >= 0);
342 assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
344 assert_se(get_process_cmdline(getpid(), 0, false, &line) == -ENOENT);
346 assert_se(get_process_cmdline(getpid(), 0, true, &line) >= 0);
347 assert_se(streq(line, "[aaaa bbbb cccc]"));
350 assert_se(get_process_cmdline(getpid(), 10, true, &line) >= 0);
351 assert_se(streq(line, "[aaaa...]"));
354 assert_se(get_process_cmdline(getpid(), 11, true, &line) >= 0);
355 assert_se(streq(line, "[aaaa...]"));
358 assert_se(get_process_cmdline(getpid(), 12, true, &line) >= 0);
359 assert_se(streq(line, "[aaaa b...]"));
366 #if 0 /// UNNEEDED by elogind
367 static void test_rename_process_one(const char *p, int ret) {
368 _cleanup_free_ char *comm = NULL, *cmdline = NULL;
378 assert_se(wait_for_terminate(pid, &si) >= 0);
379 assert_se(si.si_code == CLD_EXITED);
380 assert_se(si.si_status == EXIT_SUCCESS);
386 r = rename_process(p);
388 assert_se(r == ret ||
389 (ret == 0 && r >= 0) ||
395 #ifdef HAVE_VALGRIND_VALGRIND_H
396 /* see above, valgrind is weird, we can't verify what we are doing here */
397 if (RUNNING_ON_VALGRIND)
401 assert_se(get_process_comm(0, &comm) >= 0);
402 log_info("comm = <%s>", comm);
403 assert_se(strneq(comm, p, 15));
405 assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
406 log_info("cmdline = <%s>", cmdline);
407 assert_se(strneq(p, cmdline, strlen("test-process-util")));
408 assert_se(startswith(p, cmdline));
414 static void test_rename_process(void) {
415 test_rename_process_one(NULL, -EINVAL);
416 test_rename_process_one("", -EINVAL);
417 test_rename_process_one("foo", 1); /* should always fit */
418 test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
419 test_rename_process_one("1234567", 1); /* should always fit */
423 int main(int argc, char *argv[]) {
425 log_set_max_level(LOG_DEBUG);
426 log_parse_environment();
435 (void) parse_pid(argv[1], &pid);
436 test_get_process_comm(pid);
438 TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1));
439 test_get_process_comm(getpid());
442 test_pid_is_unwaited();
444 #if 0 /// UNNEEDED by elogind
447 test_get_process_cmdline_harder();
448 #if 0 /// UNNEEDED by elogind
449 test_rename_process();