LCOV - code coverage report
Current view: top level - test - test-process-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 224 379 59.1 %
Date: 2019-08-22 15:41:25 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <sched.h>
       4             : #include <sys/mount.h>
       5             : #include <sys/personality.h>
       6             : #include <sys/prctl.h>
       7             : #include <sys/stat.h>
       8             : #include <sys/types.h>
       9             : #include <sys/wait.h>
      10             : #include <unistd.h>
      11             : #if HAVE_VALGRIND_VALGRIND_H
      12             : #include <valgrind/valgrind.h>
      13             : #endif
      14             : 
      15             : #include "alloc-util.h"
      16             : #include "architecture.h"
      17             : #include "fd-util.h"
      18             : #include "log.h"
      19             : #include "macro.h"
      20             : #include "missing.h"
      21             : #include "parse-util.h"
      22             : #include "process-util.h"
      23             : #include "signal-util.h"
      24             : #include "stdio-util.h"
      25             : #include "string-util.h"
      26             : #include "terminal-util.h"
      27             : #include "test-helper.h"
      28             : #include "tests.h"
      29             : #include "util.h"
      30             : #include "virt.h"
      31             : 
      32           2 : static void test_get_process_comm(pid_t pid) {
      33             :         struct stat st;
      34           2 :         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
      35           4 :         _cleanup_free_ char *env = NULL;
      36             :         char path[STRLEN("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
      37             :         pid_t e;
      38             :         uid_t u;
      39             :         gid_t g;
      40             :         dev_t h;
      41             :         int r;
      42             : 
      43           2 :         xsprintf(path, "/proc/"PID_FMT"/comm", pid);
      44             : 
      45           2 :         if (stat(path, &st) == 0) {
      46           2 :                 assert_se(get_process_comm(pid, &a) >= 0);
      47           2 :                 log_info("PID"PID_FMT" comm: '%s'", pid, a);
      48             :         } else
      49           0 :                 log_warning("%s not exist.", path);
      50             : 
      51           2 :         assert_se(get_process_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0);
      52           2 :         log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
      53             : 
      54           2 :         assert_se(get_process_cmdline(pid, 8, 0, &d) >= 0);
      55           2 :         log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
      56             : 
      57           2 :         free(d);
      58           2 :         assert_se(get_process_cmdline(pid, 1, 0, &d) >= 0);
      59           2 :         log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
      60             : 
      61           2 :         assert_se(get_process_ppid(pid, &e) >= 0);
      62           2 :         log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
      63           2 :         assert_se(pid == 1 ? e == 0 : e > 0);
      64             : 
      65           2 :         assert_se(is_kernel_thread(pid) == 0 || pid != 1);
      66             : 
      67           2 :         r = get_process_exe(pid, &f);
      68           2 :         assert_se(r >= 0 || r == -EACCES);
      69           2 :         log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
      70             : 
      71           2 :         assert_se(get_process_uid(pid, &u) == 0);
      72           2 :         log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
      73             : 
      74           2 :         assert_se(get_process_gid(pid, &g) == 0);
      75           2 :         log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
      76             : 
      77           2 :         r = get_process_environ(pid, &env);
      78           2 :         assert_se(r >= 0 || r == -EACCES);
      79           2 :         log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
      80             : 
      81           2 :         if (!detect_container())
      82           2 :                 assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
      83             : 
      84           2 :         (void) getenv_for_pid(pid, "PATH", &i);
      85           2 :         log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
      86           2 : }
      87             : 
      88          10 : static void test_get_process_comm_escape_one(const char *input, const char *output) {
      89          10 :         _cleanup_free_ char *n = NULL;
      90             : 
      91          10 :         log_info("input: <%s> — output: <%s>", input, output);
      92             : 
      93          10 :         assert_se(prctl(PR_SET_NAME, input) >= 0);
      94          10 :         assert_se(get_process_comm(0, &n) >= 0);
      95             : 
      96          10 :         log_info("got: <%s>", n);
      97             : 
      98          10 :         assert_se(streq_ptr(n, output));
      99          10 : }
     100             : 
     101           1 : static void test_get_process_comm_escape(void) {
     102           1 :         _cleanup_free_ char *saved = NULL;
     103             : 
     104           1 :         assert_se(get_process_comm(0, &saved) >= 0);
     105             : 
     106           1 :         test_get_process_comm_escape_one("", "");
     107           1 :         test_get_process_comm_escape_one("foo", "foo");
     108           1 :         test_get_process_comm_escape_one("012345678901234", "012345678901234");
     109           1 :         test_get_process_comm_escape_one("0123456789012345", "012345678901234");
     110           1 :         test_get_process_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237");
     111           1 :         test_get_process_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237");
     112           1 :         test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237");
     113           1 :         test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237");
     114           1 :         test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
     115           1 :         test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
     116             : 
     117           1 :         assert_se(prctl(PR_SET_NAME, saved) >= 0);
     118           1 : }
     119             : 
     120           1 : static void test_pid_is_unwaited(void) {
     121             :         pid_t pid;
     122             : 
     123           1 :         pid = fork();
     124           1 :         assert_se(pid >= 0);
     125           1 :         if (pid == 0) {
     126           0 :                 _exit(EXIT_SUCCESS);
     127             :         } else {
     128             :                 int status;
     129             : 
     130           1 :                 waitpid(pid, &status, 0);
     131           1 :                 assert_se(!pid_is_unwaited(pid));
     132             :         }
     133           1 :         assert_se(pid_is_unwaited(getpid_cached()));
     134           1 :         assert_se(!pid_is_unwaited(-1));
     135           1 : }
     136             : 
     137           1 : static void test_pid_is_alive(void) {
     138             :         pid_t pid;
     139             : 
     140           1 :         pid = fork();
     141           1 :         assert_se(pid >= 0);
     142           1 :         if (pid == 0) {
     143           0 :                 _exit(EXIT_SUCCESS);
     144             :         } else {
     145             :                 int status;
     146             : 
     147           1 :                 waitpid(pid, &status, 0);
     148           1 :                 assert_se(!pid_is_alive(pid));
     149             :         }
     150           1 :         assert_se(pid_is_alive(getpid_cached()));
     151           1 :         assert_se(!pid_is_alive(-1));
     152           1 : }
     153             : 
     154           1 : static void test_personality(void) {
     155             : 
     156           1 :         assert_se(personality_to_string(PER_LINUX));
     157           1 :         assert_se(!personality_to_string(PERSONALITY_INVALID));
     158             : 
     159           1 :         assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
     160             : 
     161           1 :         assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
     162           1 :         assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
     163             : 
     164             : #ifdef __x86_64__
     165           1 :         assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
     166           1 :         assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
     167             : 
     168           1 :         assert_se(personality_from_string("x86-64") == PER_LINUX);
     169           1 :         assert_se(personality_from_string("x86") == PER_LINUX32);
     170           1 :         assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
     171           1 :         assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
     172             : 
     173           1 :         assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
     174             : #endif
     175           1 : }
     176             : 
     177           1 : static void test_get_process_cmdline_harder(void) {
     178           1 :         char path[] = "/tmp/test-cmdlineXXXXXX";
     179           1 :         _cleanup_close_ int fd = -1;
     180           1 :         _cleanup_free_ char *line = NULL;
     181             :         pid_t pid;
     182             : 
     183           1 :         if (geteuid() != 0) {
     184           1 :                 log_info("Skipping %s: not root", __func__);
     185           1 :                 return;
     186             :         }
     187             : 
     188           0 :         if (!have_namespaces()) {
     189           0 :                 log_notice("Testing without namespaces, skipping %s", __func__);
     190           0 :                 return;
     191             :         }
     192             : 
     193             : #if HAVE_VALGRIND_VALGRIND_H
     194             :         /* valgrind patches open(/proc//cmdline)
     195             :          * so, test_get_process_cmdline_harder fails always
     196             :          * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
     197             :         if (RUNNING_ON_VALGRIND) {
     198             :                 log_info("Skipping %s: running on valgrind", __func__);
     199             :                 return;
     200             :         }
     201             : #endif
     202             : 
     203           0 :         pid = fork();
     204           0 :         if (pid > 0) {
     205             :                 siginfo_t si;
     206             : 
     207           0 :                 (void) wait_for_terminate(pid, &si);
     208             : 
     209           0 :                 assert_se(si.si_code == CLD_EXITED);
     210           0 :                 assert_se(si.si_status == 0);
     211             : 
     212           0 :                 return;
     213             :         }
     214             : 
     215           0 :         assert_se(pid == 0);
     216           0 :         assert_se(unshare(CLONE_NEWNS) >= 0);
     217             : 
     218           0 :         if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
     219           0 :                 log_warning_errno(errno, "mount(..., \"/\", MS_SLAVE|MS_REC, ...) failed: %m");
     220           0 :                 assert_se(IN_SET(errno, EPERM, EACCES));
     221           0 :                 return;
     222             :         }
     223             : 
     224           0 :         fd = mkostemp(path, O_CLOEXEC);
     225           0 :         assert_se(fd >= 0);
     226             : 
     227             :         /* Note that we don't unmount the following bind-mount at the end of the test because the kernel
     228             :          * will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
     229           0 :         if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
     230             :                 /* This happens under selinux… Abort the test in this case. */
     231           0 :                 log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
     232           0 :                 assert_se(IN_SET(errno, EPERM, EACCES));
     233           0 :                 return;
     234             :         }
     235             : 
     236           0 :         assert_se(unlink(path) >= 0);
     237             : 
     238           0 :         assert_se(prctl(PR_SET_NAME, "testa") >= 0);
     239             : 
     240           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
     241             : 
     242           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     243           0 :         assert_se(streq(line, "[testa]"));
     244           0 :         line = mfree(line);
     245             : 
     246           0 :         assert_se(get_process_cmdline(getpid_cached(), 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     247           0 :         log_info("'%s'", line);
     248           0 :         assert_se(streq(line, ""));
     249           0 :         line = mfree(line);
     250             : 
     251           0 :         assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     252           0 :         assert_se(streq(line, "…"));
     253           0 :         line = mfree(line);
     254             : 
     255           0 :         assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     256           0 :         assert_se(streq(line, "[…"));
     257           0 :         line = mfree(line);
     258             : 
     259           0 :         assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     260           0 :         assert_se(streq(line, "[t…"));
     261           0 :         line = mfree(line);
     262             : 
     263           0 :         assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     264           0 :         assert_se(streq(line, "[te…"));
     265           0 :         line = mfree(line);
     266             : 
     267           0 :         assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     268           0 :         assert_se(streq(line, "[tes…"));
     269           0 :         line = mfree(line);
     270             : 
     271           0 :         assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     272           0 :         assert_se(streq(line, "[test…"));
     273           0 :         line = mfree(line);
     274             : 
     275           0 :         assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     276           0 :         assert_se(streq(line, "[testa]"));
     277           0 :         line = mfree(line);
     278             : 
     279           0 :         assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     280           0 :         assert_se(streq(line, "[testa]"));
     281           0 :         line = mfree(line);
     282             : 
     283           0 :         assert_se(write(fd, "foo\0bar", 8) == 8);
     284             : 
     285           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
     286           0 :         log_info("'%s'", line);
     287           0 :         assert_se(streq(line, "foo bar"));
     288           0 :         line = mfree(line);
     289             : 
     290           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     291           0 :         assert_se(streq(line, "foo bar"));
     292           0 :         line = mfree(line);
     293             : 
     294           0 :         assert_se(write(fd, "quux", 4) == 4);
     295           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0);
     296           0 :         log_info("'%s'", line);
     297           0 :         assert_se(streq(line, "foo bar quux"));
     298           0 :         line = mfree(line);
     299             : 
     300           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     301           0 :         assert_se(streq(line, "foo bar quux"));
     302           0 :         line = mfree(line);
     303             : 
     304           0 :         assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     305           0 :         assert_se(streq(line, "…"));
     306           0 :         line = mfree(line);
     307             : 
     308           0 :         assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     309           0 :         assert_se(streq(line, "f…"));
     310           0 :         line = mfree(line);
     311             : 
     312           0 :         assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     313           0 :         assert_se(streq(line, "fo…"));
     314           0 :         line = mfree(line);
     315             : 
     316           0 :         assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     317           0 :         assert_se(streq(line, "foo…"));
     318           0 :         line = mfree(line);
     319             : 
     320           0 :         assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     321           0 :         assert_se(streq(line, "foo …"));
     322           0 :         line = mfree(line);
     323             : 
     324           0 :         assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     325           0 :         assert_se(streq(line, "foo b…"));
     326           0 :         line = mfree(line);
     327             : 
     328           0 :         assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     329           0 :         assert_se(streq(line, "foo ba…"));
     330           0 :         line = mfree(line);
     331             : 
     332           0 :         assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     333           0 :         assert_se(streq(line, "foo bar…"));
     334           0 :         line = mfree(line);
     335             : 
     336           0 :         assert_se(get_process_cmdline(getpid_cached(), 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     337           0 :         assert_se(streq(line, "foo bar …"));
     338           0 :         line = mfree(line);
     339             : 
     340           0 :         assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     341           0 :         assert_se(streq(line, "foo bar q…"));
     342           0 :         line = mfree(line);
     343             : 
     344           0 :         assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     345           0 :         assert_se(streq(line, "foo bar qu…"));
     346           0 :         line = mfree(line);
     347             : 
     348           0 :         assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     349           0 :         assert_se(streq(line, "foo bar quux"));
     350           0 :         line = mfree(line);
     351             : 
     352           0 :         assert_se(get_process_cmdline(getpid_cached(), 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     353           0 :         assert_se(streq(line, "foo bar quux"));
     354           0 :         line = mfree(line);
     355             : 
     356           0 :         assert_se(get_process_cmdline(getpid_cached(), 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     357           0 :         assert_se(streq(line, "foo bar quux"));
     358           0 :         line = mfree(line);
     359             : 
     360           0 :         assert_se(get_process_cmdline(getpid_cached(), 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     361           0 :         assert_se(streq(line, "foo bar quux"));
     362           0 :         line = mfree(line);
     363             : 
     364           0 :         assert_se(ftruncate(fd, 0) >= 0);
     365           0 :         assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
     366             : 
     367           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT);
     368             : 
     369           0 :         assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     370           0 :         assert_se(streq(line, "[aaaa bbbb cccc]"));
     371           0 :         line = mfree(line);
     372             : 
     373           0 :         assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     374           0 :         assert_se(streq(line, "[aaaa bbb…"));
     375           0 :         line = mfree(line);
     376             : 
     377           0 :         assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     378           0 :         assert_se(streq(line, "[aaaa bbbb…"));
     379           0 :         line = mfree(line);
     380             : 
     381           0 :         assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0);
     382           0 :         assert_se(streq(line, "[aaaa bbbb …"));
     383           0 :         line = mfree(line);
     384             : 
     385           0 :         safe_close(fd);
     386           0 :         _exit(EXIT_SUCCESS);
     387             : }
     388             : 
     389           4 : static void test_rename_process_now(const char *p, int ret) {
     390           4 :         _cleanup_free_ char *comm = NULL, *cmdline = NULL;
     391             :         int r;
     392             : 
     393           4 :         r = rename_process(p);
     394           4 :         assert_se(r == ret ||
     395             :                   (ret == 0 && r >= 0) ||
     396             :                   (ret > 0 && r > 0));
     397             : 
     398           4 :         if (r < 0)
     399           0 :                 return;
     400             : 
     401             : #if HAVE_VALGRIND_VALGRIND_H
     402             :         /* see above, valgrind is weird, we can't verify what we are doing here */
     403             :         if (RUNNING_ON_VALGRIND)
     404             :                 return;
     405             : #endif
     406             : 
     407           4 :         assert_se(get_process_comm(0, &comm) >= 0);
     408           4 :         log_info("comm = <%s>", comm);
     409           4 :         assert_se(strneq(comm, p, TASK_COMM_LEN-1));
     410             :         /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the
     411             :          * future. We'd only check the initial part, at least until we recompile, but this will still pass. */
     412             : 
     413           4 :         r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline);
     414           4 :         assert_se(r >= 0);
     415             :         /* we cannot expect cmdline to be renamed properly without privileges */
     416           4 :         if (geteuid() == 0) {
     417           0 :                 if (r == 0 && detect_container() > 0)
     418           0 :                         log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline);
     419             :                 else {
     420           0 :                         log_info("cmdline = <%s>", cmdline);
     421           0 :                         assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
     422           0 :                         assert_se(startswith(p, cmdline));
     423             :                 }
     424             :         } else
     425           4 :                 log_info("cmdline = <%s> (not verified)", cmdline);
     426             : }
     427             : 
     428           7 : static void test_rename_process_one(const char *p, int ret) {
     429             :         siginfo_t si;
     430             :         pid_t pid;
     431             : 
     432           7 :         pid = fork();
     433           6 :         assert_se(pid >= 0);
     434             : 
     435           6 :         if (pid == 0) {
     436             :                 /* child */
     437           0 :                 test_rename_process_now(p, ret);
     438           0 :                 _exit(EXIT_SUCCESS);
     439             :         }
     440             : 
     441           6 :         assert_se(wait_for_terminate(pid, &si) >= 0);
     442           6 :         assert_se(si.si_code == CLD_EXITED);
     443           6 :         assert_se(si.si_status == EXIT_SUCCESS);
     444           6 : }
     445             : 
     446           1 : static void test_rename_process_multi(void) {
     447             :         pid_t pid;
     448             : 
     449           1 :         pid = fork();
     450           2 :         assert_se(pid >= 0);
     451             : 
     452           2 :         if (pid > 0) {
     453             :                 siginfo_t si;
     454             : 
     455           1 :                 assert_se(wait_for_terminate(pid, &si) >= 0);
     456           1 :                 assert_se(si.si_code == CLD_EXITED);
     457           1 :                 assert_se(si.si_status == EXIT_SUCCESS);
     458             : 
     459           1 :                 return;
     460             :         }
     461             : 
     462             :         /* child */
     463           1 :         test_rename_process_now("one", 1);
     464           1 :         test_rename_process_now("more", 0); /* longer than "one", hence truncated */
     465           1 :         (void) setresuid(99, 99, 99); /* change uid when running privileged */
     466           1 :         test_rename_process_now("time!", 0);
     467           1 :         test_rename_process_now("0", 1); /* shorter than "one", should fit */
     468           1 :         test_rename_process_one("", -EINVAL);
     469           1 :         test_rename_process_one(NULL, -EINVAL);
     470           0 :         _exit(EXIT_SUCCESS);
     471             : }
     472             : 
     473           1 : static void test_rename_process(void) {
     474           1 :         test_rename_process_one(NULL, -EINVAL);
     475           1 :         test_rename_process_one("", -EINVAL);
     476           1 :         test_rename_process_one("foo", 1); /* should always fit */
     477           1 :         test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
     478           1 :         test_rename_process_one("1234567", 1); /* should always fit */
     479           1 :         test_rename_process_multi(); /* multiple invocations and dropped privileges */
     480           1 : }
     481             : 
     482           1 : static void test_getpid_cached(void) {
     483             :         siginfo_t si;
     484             :         pid_t a, b, c, d, e, f, child;
     485             : 
     486           1 :         a = raw_getpid();
     487           1 :         b = getpid_cached();
     488           1 :         c = getpid();
     489             : 
     490           1 :         assert_se(a == b && a == c);
     491             : 
     492           1 :         child = fork();
     493           1 :         assert_se(child >= 0);
     494             : 
     495           1 :         if (child == 0) {
     496             :                 /* In child */
     497           0 :                 a = raw_getpid();
     498           0 :                 b = getpid_cached();
     499           0 :                 c = getpid();
     500             : 
     501           0 :                 assert_se(a == b && a == c);
     502           0 :                 _exit(EXIT_SUCCESS);
     503             :         }
     504             : 
     505           1 :         d = raw_getpid();
     506           1 :         e = getpid_cached();
     507           1 :         f = getpid();
     508             : 
     509           1 :         assert_se(a == d && a == e && a == f);
     510             : 
     511           1 :         assert_se(wait_for_terminate(child, &si) >= 0);
     512           1 :         assert_se(si.si_status == 0);
     513           1 :         assert_se(si.si_code == CLD_EXITED);
     514           1 : }
     515             : 
     516             : #define MEASURE_ITERATIONS (10000000LLU)
     517             : 
     518           1 : static void test_getpid_measure(void) {
     519             :         unsigned long long i;
     520             :         usec_t t, q;
     521             : 
     522           1 :         t = now(CLOCK_MONOTONIC);
     523    10000001 :         for (i = 0; i < MEASURE_ITERATIONS; i++)
     524    10000000 :                 (void) getpid();
     525           1 :         q = now(CLOCK_MONOTONIC) - t;
     526             : 
     527           1 :         log_info(" glibc getpid(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
     528             : 
     529           1 :         t = now(CLOCK_MONOTONIC);
     530    10000001 :         for (i = 0; i < MEASURE_ITERATIONS; i++)
     531    10000000 :                 (void) getpid_cached();
     532           1 :         q = now(CLOCK_MONOTONIC) - t;
     533             : 
     534           1 :         log_info("getpid_cached(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
     535           1 : }
     536             : 
     537           1 : static void test_safe_fork(void) {
     538             :         siginfo_t status;
     539             :         pid_t pid;
     540             :         int r;
     541             : 
     542           2 :         BLOCK_SIGNALS(SIGCHLD);
     543             : 
     544           1 :         r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
     545           1 :         assert_se(r >= 0);
     546             : 
     547           1 :         if (r == 0) {
     548             :                 /* child */
     549           0 :                 usleep(100 * USEC_PER_MSEC);
     550             : 
     551           0 :                 _exit(88);
     552             :         }
     553             : 
     554           1 :         assert_se(wait_for_terminate(pid, &status) >= 0);
     555           1 :         assert_se(status.si_code == CLD_EXITED);
     556           1 :         assert_se(status.si_status == 88);
     557           1 : }
     558             : 
     559           1 : static void test_pid_to_ptr(void) {
     560             : 
     561           1 :         assert_se(PTR_TO_PID(NULL) == 0);
     562           1 :         assert_se(PID_TO_PTR(0) == NULL);
     563             : 
     564           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1);
     565           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2);
     566           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(-1)) == -1);
     567           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(-2)) == -2);
     568             : 
     569           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MAX)) == INT16_MAX);
     570           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MIN)) == INT16_MIN);
     571             : 
     572             : #if SIZEOF_PID_T >= 4
     573           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX);
     574           1 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN);
     575             : #endif
     576           1 : }
     577             : 
     578          10 : static void test_ioprio_class_from_to_string_one(const char *val, int expected) {
     579          10 :         assert_se(ioprio_class_from_string(val) == expected);
     580          10 :         if (expected >= 0) {
     581           8 :                 _cleanup_free_ char *s = NULL;
     582             :                 unsigned ret;
     583             : 
     584           8 :                 assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
     585             :                 /* We sometimes get a class number and sometimes a number back */
     586           8 :                 assert_se(streq(s, val) ||
     587             :                           safe_atou(val, &ret) == 0);
     588             :         }
     589          10 : }
     590             : 
     591           1 : static void test_ioprio_class_from_to_string(void) {
     592           1 :         test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
     593           1 :         test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
     594           1 :         test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
     595           1 :         test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE);
     596           1 :         test_ioprio_class_from_to_string_one("0", 0);
     597           1 :         test_ioprio_class_from_to_string_one("1", 1);
     598           1 :         test_ioprio_class_from_to_string_one("7", 7);
     599           1 :         test_ioprio_class_from_to_string_one("8", 8);
     600           1 :         test_ioprio_class_from_to_string_one("9", -1);
     601           1 :         test_ioprio_class_from_to_string_one("-1", -1);
     602           1 : }
     603             : 
     604           1 : int main(int argc, char *argv[]) {
     605           1 :         test_setup_logging(LOG_DEBUG);
     606             : 
     607           1 :         save_argc_argv(argc, argv);
     608             : 
     609           1 :         if (argc > 1) {
     610           0 :                 pid_t pid = 0;
     611             : 
     612           0 :                 (void) parse_pid(argv[1], &pid);
     613           0 :                 test_get_process_comm(pid);
     614             :         } else {
     615           1 :                 TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1));
     616           1 :                 test_get_process_comm(getpid());
     617             :         }
     618             : 
     619           1 :         test_get_process_comm_escape();
     620           1 :         test_pid_is_unwaited();
     621           1 :         test_pid_is_alive();
     622           1 :         test_personality();
     623           1 :         test_get_process_cmdline_harder();
     624           1 :         test_rename_process();
     625           1 :         test_getpid_cached();
     626           1 :         test_getpid_measure();
     627           1 :         test_safe_fork();
     628           1 :         test_pid_to_ptr();
     629           1 :         test_ioprio_class_from_to_string();
     630             : 
     631           1 :         return 0;
     632             : }

Generated by: LCOV version 1.14