tree-wide: Use pidref_wait_for_terminate_and_check()

Let's use the pidref variants for waiting and
checking a process everywhere and get rid of the
non pidref variants.
This commit is contained in:
Daan De Meyer
2025-12-20 15:50:47 +01:00
parent e74b571004
commit fbd276cb86
56 changed files with 620 additions and 654 deletions
+15 -30
View File
@@ -59,53 +59,38 @@ static void test_rename_process_now(const char *p, int ret) {
}
static void test_rename_process_one(const char *p, int ret) {
siginfo_t si;
pid_t pid;
int r;
log_info("/* %s(%s) */", __func__, p);
pid = fork();
assert_se(pid >= 0);
r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (pid == 0) {
if (r == 0) {
/* child */
test_rename_process_now(p, ret);
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
assert_se(si.si_status == EXIT_SUCCESS);
}
TEST(rename_process_invalid) {
assert_se(rename_process(NULL) == -EINVAL);
assert_se(rename_process("") == -EINVAL);
ASSERT_ERROR(rename_process(NULL), EINVAL);
ASSERT_ERROR(rename_process(""), EINVAL);
}
TEST(rename_process_multi) {
pid_t pid;
int r;
pid = fork();
assert_se(pid >= 0);
r = ASSERT_OK(safe_fork("(rename)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (pid > 0) {
siginfo_t si;
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
assert_se(si.si_status == EXIT_SUCCESS);
return;
if (r == 0) {
/* child */
test_rename_process_now("one", 1);
test_rename_process_now("more", 0); /* longer than "one", hence truncated */
(void) setresuid(99, 99, 99); /* change uid when running privileged */
test_rename_process_now("time!", 0);
test_rename_process_now("0", 1); /* shorter than "one", should fit */
_exit(EXIT_SUCCESS);
}
/* child */
test_rename_process_now("one", 1);
test_rename_process_now("more", 0); /* longer than "one", hence truncated */
(void) setresuid(99, 99, 99); /* change uid when running privileged */
test_rename_process_now("time!", 0);
test_rename_process_now("0", 1); /* shorter than "one", should fit */
_exit(EXIT_SUCCESS);
}
TEST(rename_process) {
+3 -2
View File
@@ -7,6 +7,7 @@
#include "data-fd-util.h"
#include "fd-util.h"
#include "memfd-util.h"
#include "pidref.h"
#include "process-util.h"
#include "tests.h"
@@ -33,7 +34,7 @@ static void assert_equal_fd(int fd1, int fd2) {
TEST(copy_data_fd) {
_cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF;
_cleanup_close_pair_ int sfd[2] = EBADF_PAIR;
_cleanup_(sigkill_waitp) pid_t pid = -1;
_cleanup_(pidref_done_sigkill_wait) PidRef pidref = PIDREF_NULL;
int r;
fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
@@ -66,7 +67,7 @@ TEST(copy_data_fd) {
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
r = pidref_safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref);
assert_se(r >= 0);
if (r == 0) {
+7 -8
View File
@@ -246,18 +246,17 @@ static bool apparmor_restrict_unprivileged_userns(void) {
}
static bool have_userns_privileges(void) {
pid_t pid;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
int r;
if (apparmor_restrict_unprivileged_userns())
return false;
r = safe_fork("(sd-test-check-userns)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG_SIGKILL,
&pid);
ASSERT_OK(r);
r = ASSERT_OK(pidref_safe_fork(
"(sd-test-check-userns)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
&pidref));
if (r == 0) {
/* Keep CAP_SYS_ADMIN if we have it to ensure we give an
* accurate result to the caller. Some kernels have a
@@ -282,7 +281,7 @@ static bool have_userns_privileges(void) {
* EXIT_SUCCESS => we can use user namespaces
* EXIT_FAILURE => we can NOT use user namespaces
* 2 => some other error occurred */
r = wait_for_terminate_and_check("(sd-test-check-userns)", pid, 0);
r = pidref_wait_for_terminate_and_check("(sd-test-check-userns)", &pidref, 0);
if (!IN_SET(r, EXIT_SUCCESS, EXIT_FAILURE))
log_debug("Failed to check if user namespaces can be used, assuming not.");
+4 -3
View File
@@ -12,6 +12,7 @@
#include "memfd-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "random-util.h"
#include "rm-rf.h"
@@ -492,7 +493,6 @@ TEST(read_full_file_socket) {
union sockaddr_union sa;
const char *j, *jj;
size_t size;
pid_t pid;
int r;
ASSERT_OK(listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0));
@@ -513,7 +513,8 @@ TEST(read_full_file_socket) {
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
ASSERT_OK(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()));
ASSERT_OK(r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid));
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = ASSERT_OK(pidref_safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pidref));
if (r == 0) {
union sockaddr_union peer = {};
socklen_t peerlen = sizeof(peer);
@@ -540,7 +541,7 @@ TEST(read_full_file_socket) {
ASSERT_EQ(size, strlen(TEST_STR));
ASSERT_STREQ(data, TEST_STR);
ASSERT_OK(wait_for_terminate_and_check("(server)", pid, WAIT_LOG));
ASSERT_OK(pidref_wait_for_terminate_and_check("(server)", &pidref, WAIT_LOG));
#undef TEST_STR
}
+20 -20
View File
@@ -12,6 +12,7 @@
#include "fs-util.h"
#include "mkdir.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "random-util.h"
#include "rm-rf.h"
@@ -743,30 +744,29 @@ TEST(xopenat_lock_full) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
siginfo_t si;
int r;
assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0);
ASSERT_OK((tfd = mkdtemp_open(NULL, 0, &t)));
/* Test that we can acquire an exclusive lock on a directory in one process, remove the directory,
* and close the file descriptor and still properly create the directory and acquire the lock in
* another process. */
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
assert_se(fd >= 0);
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
assert_se(fd_verify_directory(fd) >= 0);
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX));
ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0));
ASSERT_OK(fd_verify_directory(fd));
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
pid_t pid = fork();
assert_se(pid >= 0);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
r = ASSERT_OK(pidref_safe_fork("(lock)", FORK_DEATHSIG_SIGKILL|FORK_LOG, &pidref));
if (pid == 0) {
if (r == 0) {
safe_close(fd);
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
assert_se(fd >= 0);
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
assert_se(fd_verify_directory(fd) >= 0);
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
fd = ASSERT_OK(xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX));
ASSERT_OK_ERRNO(faccessat(tfd, "abc", F_OK, 0));
ASSERT_OK(fd_verify_directory(fd));
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
_exit(EXIT_SUCCESS);
}
@@ -777,16 +777,16 @@ TEST(xopenat_lock_full) {
* for a little and assume that's enough time for the child process to get along far enough. It
* doesn't matter if it doesn't get far enough, in that case we just won't trigger the fallback logic
* in xopenat_lock_full(), but the test will still succeed. */
assert_se(usleep_safe(20 * USEC_PER_MSEC) >= 0);
ASSERT_OK(usleep_safe(20 * USEC_PER_MSEC));
assert_se(unlinkat(tfd, "abc", AT_REMOVEDIR) >= 0);
ASSERT_OK(unlinkat(tfd, "abc", AT_REMOVEDIR));
fd = safe_close(fd);
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
ASSERT_OK(pidref_wait_for_terminate(&pidref, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
assert_se(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
assert_se(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
ASSERT_ERROR(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF);
ASSERT_ERROR(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX), EBADF);
}
TEST(linkat_replace) {
+12 -19
View File
@@ -94,7 +94,7 @@ TEST(tmpdir) {
static void test_shareable_ns(unsigned long nsflag) {
_cleanup_close_pair_ int s[2] = EBADF_PAIR;
bool permission_denied = false;
pid_t pid1, pid2, pid3;
_cleanup_(pidref_done) PidRef pidref1 = PIDREF_NULL, pidref2 = PIDREF_NULL, pidref3 = PIDREF_NULL;
int r, n = 0;
siginfo_t si;
@@ -105,51 +105,48 @@ static void test_shareable_ns(unsigned long nsflag) {
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s));
pid1 = fork();
ASSERT_OK_ERRNO(pid1);
r = ASSERT_OK(pidref_safe_fork("(share-ns-1)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref1));
if (pid1 == 0) {
if (r == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
_exit(r >= 0 ? r : EX_NOPERM);
}
pid2 = fork();
ASSERT_OK_ERRNO(pid2);
r = ASSERT_OK(pidref_safe_fork("(share-ns-2)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref2));
if (pid2 == 0) {
if (r == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
_exit(r >= 0 ? r : EX_NOPERM);
}
pid3 = fork();
ASSERT_OK_ERRNO(pid3);
r = ASSERT_OK(pidref_safe_fork("(share-ns-3)", FORK_LOG|FORK_DEATHSIG_SIGKILL, &pidref3));
if (pid3 == 0) {
if (r == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
_exit(r >= 0 ? r : EX_NOPERM);
}
ASSERT_OK(wait_for_terminate(pid1, &si));
ASSERT_OK(pidref_wait_for_terminate(&pidref1, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
n += si.si_status;
ASSERT_OK(wait_for_terminate(pid2, &si));
ASSERT_OK(pidref_wait_for_terminate(&pidref2, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
n += si.si_status;
ASSERT_OK(wait_for_terminate(pid3, &si));
ASSERT_OK(pidref_wait_for_terminate(&pidref3, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
@@ -203,7 +200,6 @@ TEST(protect_kernel_logs) {
.protect_kernel_logs = true,
.root_directory_fd = -EBADF,
};
pid_t pid;
int r;
if (geteuid() > 0) {
@@ -224,10 +220,9 @@ TEST(protect_kernel_logs) {
}
ASSERT_OK(r);
pid = fork();
ASSERT_OK_ERRNO(pid);
r = ASSERT_OK(safe_fork("(protect)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (pid == 0) {
if (r == 0) {
_cleanup_close_ int fd = -EBADF;
ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC));
@@ -239,8 +234,6 @@ TEST(protect_kernel_logs) {
_exit(EXIT_SUCCESS);
}
ASSERT_OK_EQ(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG), EXIT_SUCCESS);
}
TEST(idmapping_supported) {
+3 -6
View File
@@ -464,7 +464,6 @@ TEST(find_executable) {
static void test_find_executable_exec_one(const char *path) {
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -EBADF;
pid_t pid;
int r;
r = find_executable_full(path, NULL, NULL, false, &t, &fd);
@@ -476,15 +475,13 @@ static void test_find_executable_exec_one(const char *path) {
if (path_is_absolute(path))
ASSERT_STREQ(t, path);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
r = ASSERT_OK(safe_fork("(find-exec)", FORK_LOG|FORK_DEATHSIG_SIGKILL|FORK_WAIT, /* ret_pid= */ NULL));
if (r == 0) {
r = fexecve_or_execve(fd, t, STRV_MAKE(t, "--version"), STRV_MAKE(NULL));
log_error_errno(r, "[f]execve: %m");
_exit(EXIT_FAILURE);
}
assert_se(wait_for_terminate_and_check(t, pid, WAIT_LOG) == 0);
}
TEST(find_executable_exec) {
+215 -231
View File
@@ -263,7 +263,6 @@ TEST(pid_get_cmdline_harder) {
_cleanup_close_ int fd = -EBADF;
_cleanup_free_ char *line = NULL;
_cleanup_strv_free_ char **args = NULL;
pid_t pid;
int r;
if (geteuid() != 0) {
@@ -286,297 +285,286 @@ TEST(pid_get_cmdline_harder) {
}
#endif
pid = fork();
if (pid > 0) {
siginfo_t si;
r = ASSERT_OK(safe_fork("(cmdline)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (r == 0) {
r = detach_mount_namespace();
if (r < 0) {
log_warning_errno(r, "detach mount namespace failed: %m");
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
return;
}
(void) wait_for_terminate(pid, &si);
fd = mkostemp(path, O_CLOEXEC);
ASSERT_OK_ERRNO(fd);
ASSERT_EQ(si.si_code, CLD_EXITED);
ASSERT_OK_ZERO(si.si_status);
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
return;
}
return;
}
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
* the cmdline. */
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning("Testing without RLIMIT_STACK=infinity");
ASSERT_OK_ZERO(pid);
ASSERT_OK_ERRNO(unlink(path));
r = detach_mount_namespace();
if (r < 0) {
log_warning_errno(r, "detach mount namespace failed: %m");
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
return;
}
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
fd = mkostemp(path, O_CLOEXEC);
ASSERT_OK_ERRNO(fd);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
* will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */
if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
ASSERT_TRUE(IN_SET(errno, EPERM, EACCES));
return;
}
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
/* Set RLIMIT_STACK to infinity to test we don't try to allocate unnecessarily large values to read
* the cmdline. */
if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning("Testing without RLIMIT_STACK=infinity");
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
line = mfree(line);
ASSERT_OK_ERRNO(unlink(path));
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[t…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_QUOTE, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "\"[testa]\""); /* quoting is enabled here */
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[te…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 0, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[tes…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[test…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[t…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[te…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[tes…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[test…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "[testa]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[testa]")));
args = strv_free(args);
/* Test with multiple arguments that don't require quoting */
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
ASSERT_OK_EQ_ERRNO(write(fd, "foo\0bar", 8), 8);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
ASSERT_STREQ(line, "foo bar");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar")));
args = strv_free(args);
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK_EQ_ERRNO(write(fd, "quux", 4), 4);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, 0, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "f…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 2, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "f…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "fo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 3, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "fo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 4, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 5, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo b…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 6, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo b…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo ba…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 7, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo ba…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 8, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 9, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar q…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar q…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar qu…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar qu…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 13, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 14, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "foo bar quux");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("foo", "bar", "quux")));
args = strv_free(args);
ASSERT_OK_ERRNO(ftruncate(fd, 0));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
ASSERT_OK_ERRNO(ftruncate(fd, 0));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb cccc]");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 10, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 11, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb…");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, 12, PROCESS_CMDLINE_COMM_FALLBACK, &line));
log_debug("'%s'", line);
ASSERT_STREQ(line, "[aaaa bbbb …");
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, PROCESS_CMDLINE_COMM_FALLBACK, &args));
ASSERT_TRUE(strv_equal(args, STRV_MAKE("[aaaa bbbb cccc]")));
args = strv_free(args);
/* Test with multiple arguments that do require quoting */
/* Test with multiple arguments that do require quoting */
#define CMDLINE1 "foo\0'bar'\0\"bar$\"\0x y z\0!``\0"
#define EXPECT1 "foo \"'bar'\" \"\\\"bar\\$\\\"\" \"x y z\" \"!\\`\\`\""
#define EXPECT1p "foo $'\\'bar\\'' $'\"bar$\"' $'x y z' $'!``'"
#define EXPECT1v STRV_MAKE("foo", "'bar'", "\"bar$\"", "x y z", "!``")
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE1, sizeof(CMDLINE1)), (ssize_t) sizeof(CMDLINE1));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof(CMDLINE1)));
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1);
ASSERT_STREQ(line, EXPECT1);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1);
ASSERT_STREQ(line, EXPECT1);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1p);
ASSERT_STREQ(line, EXPECT1p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT1p);
ASSERT_STREQ(line, EXPECT1p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT1v));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT1v));
args = strv_free(args);
#define CMDLINE2 "foo\0\1\2\3\0\0"
#define EXPECT2 "foo \"\\001\\002\\003\""
#define EXPECT2p "foo $'\\001\\002\\003'"
#define EXPECT2v STRV_MAKE("foo", "\1\2\3")
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
ASSERT_OK_ZERO_ERRNO(lseek(fd, 0, SEEK_SET));
ASSERT_OK_EQ_ERRNO(write(fd, CMDLINE2, sizeof(CMDLINE2)), (ssize_t) sizeof(CMDLINE2));
ASSERT_OK_ZERO_ERRNO(ftruncate(fd, sizeof CMDLINE2));
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2);
ASSERT_STREQ(line, EXPECT2);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2);
ASSERT_STREQ(line, EXPECT2);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2p);
ASSERT_STREQ(line, EXPECT2p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline(0, SIZE_MAX, PROCESS_CMDLINE_QUOTE_POSIX, &line));
log_debug("got: ==%s==", line);
log_debug("exp: ==%s==", EXPECT2p);
ASSERT_STREQ(line, EXPECT2p);
line = mfree(line);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT2v));
args = strv_free(args);
ASSERT_OK(pid_get_cmdline_strv(0, 0, &args));
ASSERT_TRUE(strv_equal(args, EXPECT2v));
args = strv_free(args);
safe_close(fd);
_exit(EXIT_SUCCESS);
safe_close(fd);
_exit(EXIT_SUCCESS);
}
}
TEST(getpid_cached) {
siginfo_t si;
pid_t a, b, c, d, e, f, child;
pid_t a, b, c, d, e, f;
int r;
a = getpid();
b = getpid_cached();
@@ -585,10 +573,9 @@ TEST(getpid_cached) {
ASSERT_EQ(a, b);
ASSERT_EQ(a, c);
child = fork();
ASSERT_OK_ERRNO(child);
r = ASSERT_OK(safe_fork("(getpid)", FORK_WAIT|FORK_LOG|FORK_DEATHSIG_SIGKILL, /* ret_pid= */ NULL));
if (child == 0) {
if (r == 0) {
/* In child */
a = getpid();
b = getpid_cached();
@@ -606,10 +593,6 @@ TEST(getpid_cached) {
ASSERT_EQ(a, d);
ASSERT_EQ(a, e);
ASSERT_EQ(a, f);
ASSERT_OK(wait_for_terminate(child, &si));
ASSERT_EQ(si.si_status, 0);
ASSERT_EQ(si.si_code, CLD_EXITED);
}
TEST(getpid_measure) {
@@ -641,8 +624,6 @@ TEST(safe_fork) {
pid_t pid;
int r;
BLOCK_SIGNALS(SIGCHLD);
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
ASSERT_OK(r);
@@ -653,11 +634,14 @@ TEST(safe_fork) {
_exit(88);
}
ASSERT_OK(wait_for_terminate(pid, &status));
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
ASSERT_OK(pidref_set_pid(&child, pid));
ASSERT_OK(pidref_wait_for_terminate(&child, &status));
ASSERT_EQ(status.si_code, CLD_EXITED);
ASSERT_EQ(status.si_status, 88);
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
pidref_done(&child);
r = pidref_safe_fork("(test-child)", FORK_DETACH, &child);
if (r == 0) {
/* Don't freeze so this doesn't linger around forever in case something goes wrong. */