LCOV - code coverage report
Current view: top level - test - test-process-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 224 379 59.1 %
Date: 2019-08-23 13:36:53 Functions: 18 18 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 128 458 27.9 %

           Branch data     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                 :          8 : static void test_get_process_comm(pid_t pid) {
      33                 :            :         struct stat st;
      34                 :          8 :         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
      35                 :         16 :         _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         [ -  + ]:          8 :         xsprintf(path, "/proc/"PID_FMT"/comm", pid);
      44                 :            : 
      45         [ +  - ]:          8 :         if (stat(path, &st) == 0) {
      46         [ -  + ]:          8 :                 assert_se(get_process_comm(pid, &a) >= 0);
      47         [ +  - ]:          8 :                 log_info("PID"PID_FMT" comm: '%s'", pid, a);
      48                 :            :         } else
      49         [ #  # ]:          0 :                 log_warning("%s not exist.", path);
      50                 :            : 
      51         [ -  + ]:          8 :         assert_se(get_process_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0);
      52         [ +  - ]:          8 :         log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
      53                 :            : 
      54         [ -  + ]:          8 :         assert_se(get_process_cmdline(pid, 8, 0, &d) >= 0);
      55         [ +  - ]:          8 :         log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
      56                 :            : 
      57                 :          8 :         free(d);
      58         [ -  + ]:          8 :         assert_se(get_process_cmdline(pid, 1, 0, &d) >= 0);
      59         [ +  - ]:          8 :         log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
      60                 :            : 
      61         [ -  + ]:          8 :         assert_se(get_process_ppid(pid, &e) >= 0);
      62         [ +  - ]:          8 :         log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
      63   [ +  +  -  + ]:          8 :         assert_se(pid == 1 ? e == 0 : e > 0);
      64                 :            : 
      65   [ -  +  #  # ]:          8 :         assert_se(is_kernel_thread(pid) == 0 || pid != 1);
      66                 :            : 
      67                 :          8 :         r = get_process_exe(pid, &f);
      68   [ +  +  -  + ]:          8 :         assert_se(r >= 0 || r == -EACCES);
      69         [ +  - ]:          8 :         log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
      70                 :            : 
      71         [ -  + ]:          8 :         assert_se(get_process_uid(pid, &u) == 0);
      72         [ +  - ]:          8 :         log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
      73                 :            : 
      74         [ -  + ]:          8 :         assert_se(get_process_gid(pid, &g) == 0);
      75         [ +  - ]:          8 :         log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
      76                 :            : 
      77                 :          8 :         r = get_process_environ(pid, &env);
      78   [ +  +  -  + ]:          8 :         assert_se(r >= 0 || r == -EACCES);
      79   [ +  -  +  + ]:          8 :         log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
      80                 :            : 
      81         [ +  - ]:          8 :         if (!detect_container())
      82   [ -  +  #  # ]:          8 :                 assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
      83                 :            : 
      84                 :          8 :         (void) getenv_for_pid(pid, "PATH", &i);
      85         [ +  - ]:          8 :         log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
      86                 :          8 : }
      87                 :            : 
      88                 :         40 : static void test_get_process_comm_escape_one(const char *input, const char *output) {
      89                 :         40 :         _cleanup_free_ char *n = NULL;
      90                 :            : 
      91         [ +  - ]:         40 :         log_info("input: <%s> — output: <%s>", input, output);
      92                 :            : 
      93         [ -  + ]:         40 :         assert_se(prctl(PR_SET_NAME, input) >= 0);
      94         [ -  + ]:         40 :         assert_se(get_process_comm(0, &n) >= 0);
      95                 :            : 
      96         [ +  - ]:         40 :         log_info("got: <%s>", n);
      97                 :            : 
      98         [ -  + ]:         40 :         assert_se(streq_ptr(n, output));
      99                 :         40 : }
     100                 :            : 
     101                 :          4 : static void test_get_process_comm_escape(void) {
     102                 :          4 :         _cleanup_free_ char *saved = NULL;
     103                 :            : 
     104         [ -  + ]:          4 :         assert_se(get_process_comm(0, &saved) >= 0);
     105                 :            : 
     106                 :          4 :         test_get_process_comm_escape_one("", "");
     107                 :          4 :         test_get_process_comm_escape_one("foo", "foo");
     108                 :          4 :         test_get_process_comm_escape_one("012345678901234", "012345678901234");
     109                 :          4 :         test_get_process_comm_escape_one("0123456789012345", "012345678901234");
     110                 :          4 :         test_get_process_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237");
     111                 :          4 :         test_get_process_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237");
     112                 :          4 :         test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237");
     113                 :          4 :         test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237");
     114                 :          4 :         test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
     115                 :          4 :         test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
     116                 :            : 
     117         [ -  + ]:          4 :         assert_se(prctl(PR_SET_NAME, saved) >= 0);
     118                 :          4 : }
     119                 :            : 
     120                 :          4 : static void test_pid_is_unwaited(void) {
     121                 :            :         pid_t pid;
     122                 :            : 
     123                 :          4 :         pid = fork();
     124         [ -  + ]:          4 :         assert_se(pid >= 0);
     125         [ -  + ]:          4 :         if (pid == 0) {
     126                 :          0 :                 _exit(EXIT_SUCCESS);
     127                 :            :         } else {
     128                 :            :                 int status;
     129                 :            : 
     130                 :          4 :                 waitpid(pid, &status, 0);
     131         [ -  + ]:          4 :                 assert_se(!pid_is_unwaited(pid));
     132                 :            :         }
     133         [ -  + ]:          4 :         assert_se(pid_is_unwaited(getpid_cached()));
     134         [ -  + ]:          4 :         assert_se(!pid_is_unwaited(-1));
     135                 :          4 : }
     136                 :            : 
     137                 :          4 : static void test_pid_is_alive(void) {
     138                 :            :         pid_t pid;
     139                 :            : 
     140                 :          4 :         pid = fork();
     141         [ -  + ]:          4 :         assert_se(pid >= 0);
     142         [ -  + ]:          4 :         if (pid == 0) {
     143                 :          0 :                 _exit(EXIT_SUCCESS);
     144                 :            :         } else {
     145                 :            :                 int status;
     146                 :            : 
     147                 :          4 :                 waitpid(pid, &status, 0);
     148         [ -  + ]:          4 :                 assert_se(!pid_is_alive(pid));
     149                 :            :         }
     150         [ -  + ]:          4 :         assert_se(pid_is_alive(getpid_cached()));
     151         [ -  + ]:          4 :         assert_se(!pid_is_alive(-1));
     152                 :          4 : }
     153                 :            : 
     154                 :          4 : static void test_personality(void) {
     155                 :            : 
     156         [ -  + ]:          4 :         assert_se(personality_to_string(PER_LINUX));
     157         [ -  + ]:          4 :         assert_se(!personality_to_string(PERSONALITY_INVALID));
     158                 :            : 
     159         [ -  + ]:          4 :         assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
     160                 :            : 
     161         [ -  + ]:          4 :         assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
     162         [ -  + ]:          4 :         assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
     163                 :            : 
     164                 :            : #ifdef __x86_64__
     165         [ -  + ]:          4 :         assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
     166         [ -  + ]:          4 :         assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
     167                 :            : 
     168         [ -  + ]:          4 :         assert_se(personality_from_string("x86-64") == PER_LINUX);
     169         [ -  + ]:          4 :         assert_se(personality_from_string("x86") == PER_LINUX32);
     170         [ -  + ]:          4 :         assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
     171         [ -  + ]:          4 :         assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
     172                 :            : 
     173         [ -  + ]:          4 :         assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
     174                 :            : #endif
     175                 :          4 : }
     176                 :            : 
     177                 :          4 : static void test_get_process_cmdline_harder(void) {
     178                 :          4 :         char path[] = "/tmp/test-cmdlineXXXXXX";
     179                 :          4 :         _cleanup_close_ int fd = -1;
     180                 :          4 :         _cleanup_free_ char *line = NULL;
     181                 :            :         pid_t pid;
     182                 :            : 
     183         [ +  - ]:          4 :         if (geteuid() != 0) {
     184         [ +  - ]:          4 :                 log_info("Skipping %s: not root", __func__);
     185                 :          4 :                 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                 :         16 : static void test_rename_process_now(const char *p, int ret) {
     390   [ +  -  +  - ]:         16 :         _cleanup_free_ char *comm = NULL, *cmdline = NULL;
     391                 :            :         int r;
     392                 :            : 
     393                 :         16 :         r = rename_process(p);
     394   [ -  +  #  #  :         16 :         assert_se(r == ret ||
          #  #  #  #  -  
          +  #  #  #  #  
                   #  # ]
     395                 :            :                   (ret == 0 && r >= 0) ||
     396                 :            :                   (ret > 0 && r > 0));
     397                 :            : 
     398         [ -  + ]:         16 :         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         [ -  + ]:         16 :         assert_se(get_process_comm(0, &comm) >= 0);
     408         [ +  - ]:         16 :         log_info("comm = <%s>", comm);
     409         [ -  + ]:         16 :         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                 :         16 :         r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline);
     414         [ -  + ]:         16 :         assert_se(r >= 0);
     415                 :            :         /* we cannot expect cmdline to be renamed properly without privileges */
     416         [ -  + ]:         16 :         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         [ +  - ]:         16 :                 log_info("cmdline = <%s> (not verified)", cmdline);
     426                 :            : }
     427                 :            : 
     428                 :         28 : static void test_rename_process_one(const char *p, int ret) {
     429                 :            :         siginfo_t si;
     430                 :            :         pid_t pid;
     431                 :            : 
     432                 :         28 :         pid = fork();
     433         [ -  + ]:         24 :         assert_se(pid >= 0);
     434                 :            : 
     435         [ -  + ]:         24 :         if (pid == 0) {
     436                 :            :                 /* child */
     437                 :          0 :                 test_rename_process_now(p, ret);
     438                 :          0 :                 _exit(EXIT_SUCCESS);
     439                 :            :         }
     440                 :            : 
     441         [ -  + ]:         24 :         assert_se(wait_for_terminate(pid, &si) >= 0);
     442         [ -  + ]:         24 :         assert_se(si.si_code == CLD_EXITED);
     443         [ -  + ]:         24 :         assert_se(si.si_status == EXIT_SUCCESS);
     444                 :         24 : }
     445                 :            : 
     446                 :          4 : static void test_rename_process_multi(void) {
     447                 :            :         pid_t pid;
     448                 :            : 
     449                 :          4 :         pid = fork();
     450         [ -  + ]:          8 :         assert_se(pid >= 0);
     451                 :            : 
     452         [ +  + ]:          8 :         if (pid > 0) {
     453                 :            :                 siginfo_t si;
     454                 :            : 
     455         [ -  + ]:          4 :                 assert_se(wait_for_terminate(pid, &si) >= 0);
     456         [ -  + ]:          4 :                 assert_se(si.si_code == CLD_EXITED);
     457         [ -  + ]:          4 :                 assert_se(si.si_status == EXIT_SUCCESS);
     458                 :            : 
     459                 :          4 :                 return;
     460                 :            :         }
     461                 :            : 
     462                 :            :         /* child */
     463                 :          4 :         test_rename_process_now("one", 1);
     464                 :          4 :         test_rename_process_now("more", 0); /* longer than "one", hence truncated */
     465                 :          4 :         (void) setresuid(99, 99, 99); /* change uid when running privileged */
     466                 :          4 :         test_rename_process_now("time!", 0);
     467                 :          4 :         test_rename_process_now("0", 1); /* shorter than "one", should fit */
     468                 :          4 :         test_rename_process_one("", -EINVAL);
     469                 :          4 :         test_rename_process_one(NULL, -EINVAL);
     470                 :          0 :         _exit(EXIT_SUCCESS);
     471                 :            : }
     472                 :            : 
     473                 :          4 : static void test_rename_process(void) {
     474                 :          4 :         test_rename_process_one(NULL, -EINVAL);
     475                 :          4 :         test_rename_process_one("", -EINVAL);
     476                 :          4 :         test_rename_process_one("foo", 1); /* should always fit */
     477                 :          4 :         test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
     478                 :          4 :         test_rename_process_one("1234567", 1); /* should always fit */
     479                 :          4 :         test_rename_process_multi(); /* multiple invocations and dropped privileges */
     480                 :          4 : }
     481                 :            : 
     482                 :          4 : static void test_getpid_cached(void) {
     483                 :            :         siginfo_t si;
     484                 :            :         pid_t a, b, c, d, e, f, child;
     485                 :            : 
     486                 :          4 :         a = raw_getpid();
     487                 :          4 :         b = getpid_cached();
     488                 :          4 :         c = getpid();
     489                 :            : 
     490   [ +  -  -  + ]:          4 :         assert_se(a == b && a == c);
     491                 :            : 
     492                 :          4 :         child = fork();
     493         [ -  + ]:          4 :         assert_se(child >= 0);
     494                 :            : 
     495         [ -  + ]:          4 :         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                 :          4 :         d = raw_getpid();
     506                 :          4 :         e = getpid_cached();
     507                 :          4 :         f = getpid();
     508                 :            : 
     509   [ +  -  -  +  :          4 :         assert_se(a == d && a == e && a == f);
             +  -  -  + ]
     510                 :            : 
     511         [ -  + ]:          4 :         assert_se(wait_for_terminate(child, &si) >= 0);
     512         [ -  + ]:          4 :         assert_se(si.si_status == 0);
     513         [ -  + ]:          4 :         assert_se(si.si_code == CLD_EXITED);
     514                 :          4 : }
     515                 :            : 
     516                 :            : #define MEASURE_ITERATIONS (10000000LLU)
     517                 :            : 
     518                 :          4 : static void test_getpid_measure(void) {
     519                 :            :         unsigned long long i;
     520                 :            :         usec_t t, q;
     521                 :            : 
     522                 :          4 :         t = now(CLOCK_MONOTONIC);
     523         [ +  + ]:   40000004 :         for (i = 0; i < MEASURE_ITERATIONS; i++)
     524                 :   40000000 :                 (void) getpid();
     525                 :          4 :         q = now(CLOCK_MONOTONIC) - t;
     526                 :            : 
     527         [ +  - ]:          4 :         log_info(" glibc getpid(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
     528                 :            : 
     529                 :          4 :         t = now(CLOCK_MONOTONIC);
     530         [ +  + ]:   40000004 :         for (i = 0; i < MEASURE_ITERATIONS; i++)
     531                 :   40000000 :                 (void) getpid_cached();
     532                 :          4 :         q = now(CLOCK_MONOTONIC) - t;
     533                 :            : 
     534         [ +  - ]:          4 :         log_info("getpid_cached(): %lf µs each\n", (double) q / MEASURE_ITERATIONS);
     535                 :          4 : }
     536                 :            : 
     537                 :          4 : static void test_safe_fork(void) {
     538                 :            :         siginfo_t status;
     539                 :            :         pid_t pid;
     540                 :            :         int r;
     541                 :            : 
     542         [ -  + ]:          8 :         BLOCK_SIGNALS(SIGCHLD);
     543                 :            : 
     544                 :          4 :         r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
     545         [ -  + ]:          4 :         assert_se(r >= 0);
     546                 :            : 
     547         [ -  + ]:          4 :         if (r == 0) {
     548                 :            :                 /* child */
     549                 :          0 :                 usleep(100 * USEC_PER_MSEC);
     550                 :            : 
     551                 :          0 :                 _exit(88);
     552                 :            :         }
     553                 :            : 
     554         [ -  + ]:          4 :         assert_se(wait_for_terminate(pid, &status) >= 0);
     555         [ -  + ]:          4 :         assert_se(status.si_code == CLD_EXITED);
     556         [ -  + ]:          4 :         assert_se(status.si_status == 88);
     557                 :          4 : }
     558                 :            : 
     559                 :          4 : static void test_pid_to_ptr(void) {
     560                 :            : 
     561         [ -  + ]:          4 :         assert_se(PTR_TO_PID(NULL) == 0);
     562         [ -  + ]:          4 :         assert_se(PID_TO_PTR(0) == NULL);
     563                 :            : 
     564         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1);
     565         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2);
     566         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(-1)) == -1);
     567         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(-2)) == -2);
     568                 :            : 
     569         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MAX)) == INT16_MAX);
     570         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MIN)) == INT16_MIN);
     571                 :            : 
     572                 :            : #if SIZEOF_PID_T >= 4
     573         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX);
     574         [ -  + ]:          4 :         assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN);
     575                 :            : #endif
     576                 :          4 : }
     577                 :            : 
     578                 :         40 : static void test_ioprio_class_from_to_string_one(const char *val, int expected) {
     579         [ -  + ]:         40 :         assert_se(ioprio_class_from_string(val) == expected);
     580         [ +  + ]:         40 :         if (expected >= 0) {
     581                 :         32 :                 _cleanup_free_ char *s = NULL;
     582                 :            :                 unsigned ret;
     583                 :            : 
     584         [ -  + ]:         32 :                 assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
     585                 :            :                 /* We sometimes get a class number and sometimes a number back */
     586   [ +  +  -  + ]:         32 :                 assert_se(streq(s, val) ||
     587                 :            :                           safe_atou(val, &ret) == 0);
     588                 :            :         }
     589                 :         40 : }
     590                 :            : 
     591                 :          4 : static void test_ioprio_class_from_to_string(void) {
     592                 :          4 :         test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
     593                 :          4 :         test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
     594                 :          4 :         test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
     595                 :          4 :         test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE);
     596                 :          4 :         test_ioprio_class_from_to_string_one("0", 0);
     597                 :          4 :         test_ioprio_class_from_to_string_one("1", 1);
     598                 :          4 :         test_ioprio_class_from_to_string_one("7", 7);
     599                 :          4 :         test_ioprio_class_from_to_string_one("8", 8);
     600                 :          4 :         test_ioprio_class_from_to_string_one("9", -1);
     601                 :          4 :         test_ioprio_class_from_to_string_one("-1", -1);
     602                 :          4 : }
     603                 :            : 
     604                 :          4 : int main(int argc, char *argv[]) {
     605                 :          4 :         test_setup_logging(LOG_DEBUG);
     606                 :            : 
     607                 :          4 :         save_argc_argv(argc, argv);
     608                 :            : 
     609         [ -  + ]:          4 :         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         [ +  - ]:          4 :                 TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1));
     616                 :          4 :                 test_get_process_comm(getpid());
     617                 :            :         }
     618                 :            : 
     619                 :          4 :         test_get_process_comm_escape();
     620                 :          4 :         test_pid_is_unwaited();
     621                 :          4 :         test_pid_is_alive();
     622                 :          4 :         test_personality();
     623                 :          4 :         test_get_process_cmdline_harder();
     624                 :          4 :         test_rename_process();
     625                 :          4 :         test_getpid_cached();
     626                 :          4 :         test_getpid_measure();
     627                 :          4 :         test_safe_fork();
     628                 :          4 :         test_pid_to_ptr();
     629                 :          4 :         test_ioprio_class_from_to_string();
     630                 :            : 
     631                 :          4 :         return 0;
     632                 :            : }

Generated by: LCOV version 1.14