]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: move a bunch of cmdline-related funcs to new argv-util.c+h
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 6 Nov 2022 15:45:48 +0000 (16:45 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 8 Nov 2022 17:21:10 +0000 (18:21 +0100)
I wanted to move saved_arg[cv] to process-util.c+h, but this causes problems:
process-util.h includes format-util.h which includes net/if.h, which conflicts
with linux/if.h. So we can't include process-util.h in some files.

But process-util.c is very long anyway, so it seems nice to create a new file.
rename_process(), invoked_as(), invoked_by_systemd(), and argv_looks_like_help()
which lived in process-util.c refer to saved_argc and saved_argv, so it seems
reasonable to move them to the new file too.

util.c is now empty, so it is removed. util.h remains.

18 files changed:
src/basic/argv-util.c [new file with mode: 0644]
src/basic/argv-util.h [new file with mode: 0644]
src/basic/log.c
src/basic/meson.build
src/basic/process-util.c
src/basic/process-util.h
src/basic/util.c [deleted file]
src/basic/util.h
src/core/execute.c
src/core/main.c
src/nspawn/nspawn-stub-pid1.c
src/shared/main-func.h
src/shared/tests.h
src/systemctl/systemctl-switch-root.c
src/test/meson.build
src/test/test-argv-util.c [new file with mode: 0644]
src/test/test-netlink-manual.c
src/test/test-process-util.c

diff --git a/src/basic/argv-util.c b/src/basic/argv-util.c
new file mode 100644 (file)
index 0000000..54649f4
--- /dev/null
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <sched.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#include "argv-util.h"
+#include "errno-util.h"
+#include "missing_sched.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "string-util.h"
+#include "strv.h"
+
+int saved_argc = 0;
+char **saved_argv = NULL;
+
+bool invoked_as(char *argv[], const char *token) {
+        if (!argv || isempty(argv[0]))
+                return false;
+
+        if (isempty(token))
+                return false;
+
+        return strstr(last_path_component(argv[0]), token);
+}
+
+bool invoked_by_systemd(void) {
+        int r;
+
+        /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
+         * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
+        const char *e = getenv("SYSTEMD_EXEC_PID");
+        if (!e)
+                return false;
+
+        if (streq(e, "*"))
+                /* For testing. */
+                return true;
+
+        pid_t p;
+        r = parse_pid(e, &p);
+        if (r < 0) {
+                /* We know that systemd sets the variable correctly. Something else must have set it. */
+                log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
+                return false;
+        }
+
+        return getpid_cached() == p;
+}
+
+bool argv_looks_like_help(int argc, char **argv) {
+        char **l;
+
+        /* Scans the command line for indications the user asks for help. This is supposed to be called by
+         * tools that do not implement getopt() style command line parsing because they are not primarily
+         * user-facing. Detects four ways of asking for help:
+         *
+         * 1. Passing zero arguments
+         * 2. Passing "help" as first argument
+         * 3. Passing --help as any argument
+         * 4. Passing -h as any argument
+         */
+
+        if (argc <= 1)
+                return true;
+
+        if (streq_ptr(argv[1], "help"))
+                return true;
+
+        l = strv_skip(argv, 1);
+
+        return strv_contains(l, "--help") ||
+                strv_contains(l, "-h");
+}
+
+static int update_argv(const char name[], size_t l) {
+        static int can_do = -1;
+
+        if (can_do == 0)
+                return 0;
+        can_do = false; /* We'll set it to true only if the whole process works */
+
+        /* Let's not bother with this if we don't have euid == 0. Strictly speaking we should check for the
+         * CAP_SYS_RESOURCE capability which is independent of the euid. In our own code the capability generally is
+         * present only for euid == 0, hence let's use this as quick bypass check, to avoid calling mmap() if
+         * PR_SET_MM_ARG_{START,END} fails with EPERM later on anyway. After all geteuid() is dead cheap to call, but
+         * mmap() is not. */
+        if (geteuid() != 0)
+                return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
+                                       "Skipping PR_SET_MM, as we don't have privileges.");
+
+        static size_t mm_size = 0;
+        static char *mm = NULL;
+        int r;
+
+        if (mm_size < l+1) {
+                size_t nn_size;
+                char *nn;
+
+                nn_size = PAGE_ALIGN(l+1);
+                nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+                if (nn == MAP_FAILED)
+                        return log_debug_errno(errno, "mmap() failed: %m");
+
+                strncpy(nn, name, nn_size);
+
+                /* Now, let's tell the kernel about this new memory */
+                if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
+                        if (ERRNO_IS_PRIVILEGE(errno))
+                                return log_debug_errno(errno, "PR_SET_MM_ARG_START failed: %m");
+
+                        /* HACK: prctl() API is kind of dumb on this point.  The existing end address may already be
+                         * below the desired start address, in which case the kernel may have kicked this back due
+                         * to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in
+                         * action).  The proper solution would be to have a prctl() API that could set both start+end
+                         * simultaneously, or at least let us query the existing address to anticipate this condition
+                         * and respond accordingly.  For now, we can only guess at the cause of this failure and try
+                         * a workaround--which will briefly expand the arg space to something potentially huge before
+                         * resizing it to what we want. */
+                        log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m");
+
+                        if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) {
+                                r = log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
+                                (void) munmap(nn, nn_size);
+                                return r;
+                        }
+
+                        if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0)
+                                return log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
+                } else {
+                        /* And update the end pointer to the new end, too. If this fails, we don't really know what
+                         * to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure,
+                         * and continue. */
+                        if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
+                                log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+                }
+
+                if (mm)
+                        (void) munmap(mm, mm_size);
+
+                mm = nn;
+                mm_size = nn_size;
+        } else {
+                strncpy(mm, name, mm_size);
+
+                /* Update the end pointer, continuing regardless of any failure. */
+                if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) mm + l + 1, 0, 0) < 0)
+                        log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
+        }
+
+        can_do = true;
+        return 0;
+}
+
+int rename_process(const char name[]) {
+        bool truncated = false;
+
+        /* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
+         * internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
+         * many cases one of 10 (i.e. length of "/sbin/init") — however if we have CAP_SYS_RESOURCES it is unbounded;
+         * to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
+         * truncated.
+         *
+         * Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
+
+        if (isempty(name))
+                return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
+
+        if (!is_main_thread())
+                return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
+                                * cache things without locking, and we make assumptions that PR_SET_NAME sets the
+                                * process name that isn't correct on any other threads */
+
+        size_t l = strlen(name);
+
+        /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
+         * can use PR_SET_NAME, which sets the thread name for the calling thread. */
+        if (prctl(PR_SET_NAME, name) < 0)
+                log_debug_errno(errno, "PR_SET_NAME failed: %m");
+        if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
+                truncated = true;
+
+        /* Second step, change glibc's ID of the process name. */
+        if (program_invocation_name) {
+                size_t k;
+
+                k = strlen(program_invocation_name);
+                strncpy(program_invocation_name, name, k);
+                if (l > k)
+                        truncated = true;
+        }
+
+        /* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
+         * has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
+         * the end. This is the best option for changing /proc/self/cmdline. */
+        (void) update_argv(name, l);
+
+        /* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
+         * it still looks here */
+        if (saved_argc > 0) {
+                if (saved_argv[0]) {
+                        size_t k;
+
+                        k = strlen(saved_argv[0]);
+                        strncpy(saved_argv[0], name, k);
+                        if (l > k)
+                                truncated = true;
+                }
+
+                for (int i = 1; i < saved_argc; i++) {
+                        if (!saved_argv[i])
+                                break;
+
+                        memzero(saved_argv[i], strlen(saved_argv[i]));
+                }
+        }
+
+        return !truncated;
+}
diff --git a/src/basic/argv-util.h b/src/basic/argv-util.h
new file mode 100644 (file)
index 0000000..a20a951
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+extern int saved_argc;
+extern char **saved_argv;
+
+static inline void save_argc_argv(int argc, char **argv) {
+        /* Protect against CVE-2021-4034 style attacks */
+        assert_se(argc > 0);
+        assert_se(argv);
+        assert_se(argv[0]);
+
+        saved_argc = argc;
+        saved_argv = argv;
+}
+
+bool invoked_as(char *argv[], const char *token);
+bool invoked_by_systemd(void);
+bool argv_looks_like_help(int argc, char **argv);
+
+int rename_process(const char name[]);
index 39d08b092895c5da40b781023f54a7b6d15e28c9..173643196e7dbbc9d45f216bf5563876200bfb7f 100644 (file)
@@ -16,6 +16,7 @@
 #include "sd-messages.h"
 
 #include "alloc-util.h"
+#include "argv-util.h"
 #include "errno-util.h"
 #include "fd-util.h"
 #include "format-util.h"
index c1d970b6a9f706f307355b7f2168f227c2a5b792..c5dd116964d255f5f741841951bba2ca15da390e 100644 (file)
@@ -9,6 +9,8 @@ basic_sources = files(
         'alloc-util.h',
         'architecture.c',
         'architecture.h',
+        'argv-util.c',
+        'argv-util.h',
         'arphrd-util.c',
         'arphrd-util.h',
         'async.c',
@@ -256,7 +258,6 @@ basic_sources = files(
         'user-util.h',
         'utf8.c',
         'utf8.h',
-        'util.c',
         'util.h',
         'virt.c',
         'virt.h',
index 6e4a56b0aac14790a3145daf53feafb7c61ec9ac..dd913bc3238e6a9fe90a6aee57d22bc11124d83c 100644 (file)
@@ -8,7 +8,6 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/mman.h>
 #include <sys/mount.h>
 #include <sys/personality.h>
 #include <sys/prctl.h>
@@ -22,6 +21,7 @@
 
 #include "alloc-util.h"
 #include "architecture.h"
+#include "argv-util.h"
 #include "env-file.h"
 #include "env-util.h"
 #include "errno-util.h"
@@ -297,151 +297,6 @@ int container_get_leader(const char *machine, pid_t *pid) {
         return 0;
 }
 
-static int update_argv(const char name[], size_t l) {
-        static int can_do = -1;
-
-        if (can_do == 0)
-                return 0;
-        can_do = false; /* We'll set it to true only if the whole process works */
-
-        /* Let's not bother with this if we don't have euid == 0. Strictly speaking we should check for the
-         * CAP_SYS_RESOURCE capability which is independent of the euid. In our own code the capability generally is
-         * present only for euid == 0, hence let's use this as quick bypass check, to avoid calling mmap() if
-         * PR_SET_MM_ARG_{START,END} fails with EPERM later on anyway. After all geteuid() is dead cheap to call, but
-         * mmap() is not. */
-        if (geteuid() != 0)
-                return log_debug_errno(SYNTHETIC_ERRNO(EPERM),
-                                       "Skipping PR_SET_MM, as we don't have privileges.");
-
-        static size_t mm_size = 0;
-        static char *mm = NULL;
-        int r;
-
-        if (mm_size < l+1) {
-                size_t nn_size;
-                char *nn;
-
-                nn_size = PAGE_ALIGN(l+1);
-                nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-                if (nn == MAP_FAILED)
-                        return log_debug_errno(errno, "mmap() failed: %m");
-
-                strncpy(nn, name, nn_size);
-
-                /* Now, let's tell the kernel about this new memory */
-                if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) {
-                        if (ERRNO_IS_PRIVILEGE(errno))
-                                return log_debug_errno(errno, "PR_SET_MM_ARG_START failed: %m");
-
-                        /* HACK: prctl() API is kind of dumb on this point.  The existing end address may already be
-                         * below the desired start address, in which case the kernel may have kicked this back due
-                         * to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in
-                         * action).  The proper solution would be to have a prctl() API that could set both start+end
-                         * simultaneously, or at least let us query the existing address to anticipate this condition
-                         * and respond accordingly.  For now, we can only guess at the cause of this failure and try
-                         * a workaround--which will briefly expand the arg space to something potentially huge before
-                         * resizing it to what we want. */
-                        log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m");
-
-                        if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) {
-                                r = log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m");
-                                (void) munmap(nn, nn_size);
-                                return r;
-                        }
-
-                        if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0)
-                                return log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m");
-                } else {
-                        /* And update the end pointer to the new end, too. If this fails, we don't really know what
-                         * to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure,
-                         * and continue. */
-                        if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0)
-                                log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
-                }
-
-                if (mm)
-                        (void) munmap(mm, mm_size);
-
-                mm = nn;
-                mm_size = nn_size;
-        } else {
-                strncpy(mm, name, mm_size);
-
-                /* Update the end pointer, continuing regardless of any failure. */
-                if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) mm + l + 1, 0, 0) < 0)
-                        log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m");
-        }
-
-        can_do = true;
-        return 0;
-}
-
-int rename_process(const char name[]) {
-        bool truncated = false;
-
-        /* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's
-         * internally used name of the process. For the first one a limit of 16 chars applies; to the second one in
-         * many cases one of 10 (i.e. length of "/sbin/init") — however if we have CAP_SYS_RESOURCES it is unbounded;
-         * to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be
-         * truncated.
-         *
-         * Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */
-
-        if (isempty(name))
-                return -EINVAL; /* let's not confuse users unnecessarily with an empty name */
-
-        if (!is_main_thread())
-                return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we
-                                * cache things without locking, and we make assumptions that PR_SET_NAME sets the
-                                * process name that isn't correct on any other threads */
-
-        size_t l = strlen(name);
-
-        /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we
-         * can use PR_SET_NAME, which sets the thread name for the calling thread. */
-        if (prctl(PR_SET_NAME, name) < 0)
-                log_debug_errno(errno, "PR_SET_NAME failed: %m");
-        if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
-                truncated = true;
-
-        /* Second step, change glibc's ID of the process name. */
-        if (program_invocation_name) {
-                size_t k;
-
-                k = strlen(program_invocation_name);
-                strncpy(program_invocation_name, name, k);
-                if (l > k)
-                        truncated = true;
-        }
-
-        /* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but
-         * has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at
-         * the end. This is the best option for changing /proc/self/cmdline. */
-        (void) update_argv(name, l);
-
-        /* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if
-         * it still looks here */
-        if (saved_argc > 0) {
-                if (saved_argv[0]) {
-                        size_t k;
-
-                        k = strlen(saved_argv[0]);
-                        strncpy(saved_argv[0], name, k);
-                        if (l > k)
-                                truncated = true;
-                }
-
-                for (int i = 1; i < saved_argc; i++) {
-                        if (!saved_argv[i])
-                                break;
-
-                        memzero(saved_argv[i], strlen(saved_argv[i]));
-                }
-        }
-
-        return !truncated;
-}
-
 int is_kernel_thread(pid_t pid) {
         _cleanup_free_ char *line = NULL;
         unsigned long long flags;
@@ -1627,40 +1482,6 @@ int setpriority_closest(int priority) {
         return 0;
 }
 
-bool invoked_as(char *argv[], const char *token) {
-        if (!argv || isempty(argv[0]))
-                return false;
-
-        if (isempty(token))
-                return false;
-
-        return strstr(last_path_component(argv[0]), token);
-}
-
-bool invoked_by_systemd(void) {
-        int r;
-
-        /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
-         * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
-        const char *e = getenv("SYSTEMD_EXEC_PID");
-        if (!e)
-                return false;
-
-        if (streq(e, "*"))
-                /* For testing. */
-                return true;
-
-        pid_t p;
-        r = parse_pid(e, &p);
-        if (r < 0) {
-                /* We know that systemd sets the variable correctly. Something else must have set it. */
-                log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
-                return false;
-        }
-
-        return getpid_cached() == p;
-}
-
 _noreturn_ void freeze(void) {
         log_close();
 
@@ -1682,31 +1503,6 @@ _noreturn_ void freeze(void) {
                 pause();
 }
 
-bool argv_looks_like_help(int argc, char **argv) {
-        char **l;
-
-        /* Scans the command line for indications the user asks for help. This is supposed to be called by
-         * tools that do not implement getopt() style command line parsing because they are not primarily
-         * user-facing. Detects four ways of asking for help:
-         *
-         * 1. Passing zero arguments
-         * 2. Passing "help" as first argument
-         * 3. Passing --help as any argument
-         * 4. Passing -h as any argument
-         */
-
-        if (argc <= 1)
-                return true;
-
-        if (streq_ptr(argv[1], "help"))
-                return true;
-
-        l = strv_skip(argv, 1);
-
-        return strv_contains(l, "--help") ||
-                strv_contains(l, "-h");
-}
-
 static const char *const sigchld_code_table[] = {
         [CLD_EXITED] = "exited",
         [CLD_KILLED] = "killed",
index d5986ad64699d4a78cf67e50d0295ec7091a9ea3..83663670ac485214adbac653865a9f09c4ed9831 100644 (file)
@@ -71,7 +71,6 @@ void sigterm_wait(pid_t pid);
 
 int kill_and_sigcont(pid_t pid, int sig);
 
-int rename_process(const char name[]);
 int is_kernel_thread(pid_t pid);
 
 int getenv_for_pid(pid_t pid, const char *field, char **_value);
@@ -191,10 +190,4 @@ int pidfd_get_pid(int fd, pid_t *ret);
 
 int setpriority_closest(int priority);
 
-bool invoked_as(char *argv[], const char *token);
-
-bool invoked_by_systemd(void);
-
 _noreturn_ void freeze(void);
-
-bool argv_looks_like_help(int argc, char **argv);
diff --git a/src/basic/util.c b/src/basic/util.c
deleted file mode 100644 (file)
index e5e61e6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "alloc-util.h"
-#include "build.h"
-#include "env-file.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "hostname-util.h"
-#include "log.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "stat-util.h"
-#include "string-util.h"
-#include "util.h"
-#include "virt.h"
-
-int saved_argc = 0;
-char **saved_argv = NULL;
index 95f71a66eddf84fd36e00c712c2814c10ecc905d..646f2d3613a39727360ab57391bcc8692e3dea90 100644 (file)
@@ -5,20 +5,6 @@
 
 #include "macro.h"
 
-extern int saved_argc;
-extern char **saved_argv;
-
-static inline void save_argc_argv(int argc, char **argv) {
-
-        /* Protect against CVE-2021-4034 style attacks */
-        assert_se(argc > 0);
-        assert_se(argv);
-        assert_se(argv[0]);
-
-        saved_argc = argc;
-        saved_argv = argv;
-}
-
 /* Note: log2(0) == log2(1) == 0 here and below. */
 
 #define CONST_LOG2ULL(x) ((x) > 1 ? (unsigned) __builtin_clzll(x) ^ 63U : 0)
index b5b7de6d2a008178b25740b094c6fed73c75486d..981bb63440cb1359db412fbc5a5a7868f4cd02f8 100644 (file)
@@ -39,6 +39,7 @@
 #if HAVE_APPARMOR
 #include "apparmor-util.h"
 #endif
+#include "argv-util.h"
 #include "async.h"
 #include "barrier.h"
 #include "bpf-lsm.h"
index 672345368cce6036ae5894e89eb9cbfbd014fd8c..4cf5dd146b3b81fa2e086dd5a11ffe4e31862dfe 100644 (file)
@@ -22,6 +22,7 @@
 #include "alloc-util.h"
 #include "apparmor-setup.h"
 #include "architecture.h"
+#include "argv-util.h"
 #if HAVE_LIBBPF
 #include "bpf-lsm.h"
 #endif
index 85c439815c6ddcb332f62fe98ef6841825b4ea7a..cea5f94b2e9184800fd3370c7965b28aa6dcad7c 100644 (file)
@@ -6,6 +6,7 @@
 #include <sys/prctl.h>
 #include <unistd.h>
 
+#include "argv-util.h"
 #include "def.h"
 #include "exit-status.h"
 #include "fd-util.h"
index 81a5c1813cb37b18613bd51aed17999b447536b0..3dc49922821a57260e1a000370bdd30bc658a362 100644 (file)
@@ -5,12 +5,12 @@
 
 #include "sd-daemon.h"
 
+#include "argv-util.h"
 #include "pager.h"
 #include "selinux-util.h"
 #include "spawn-ask-password-agent.h"
 #include "spawn-polkit-agent.h"
 #include "static-destruct.h"
-#include "util.h"
 
 #define _DEFINE_MAIN_FUNCTION(intro, impl, ret)                         \
         int main(int argc, char *argv[]) {                              \
index a2f7f38c41e0b2b440cc65ea12124ce556cc47fc..cabd659fbdf46001f370afe9dec0f3c3beef41c6 100644 (file)
@@ -5,9 +5,9 @@
 
 #include "sd-daemon.h"
 
+#include "argv-util.h"
 #include "macro.h"
 #include "static-destruct.h"
-#include "util.h"
 
 static inline bool manager_errno_skip_test(int r) {
         return IN_SET(abs(r),
index 669fa60dfdd65263bf396e5f5cbaa2aaba92e26a..8a7749be91d83ffbb937763c461c7c2a04e5b7a1 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "argv-util.h"
 #include "bus-error.h"
 #include "bus-locator.h"
 #include "parse-util.h"
index 0c6f2db4283399f4b81e10e3ef00418cd073bd8a..413dcdec6214cd643f3eafdace5180980685c5b6 100644 (file)
@@ -41,6 +41,8 @@ test_dlopen_c = files('test-dlopen.c')
 ############################################################
 
 tests += [
+        [files('test-argv-util.c')],
+
         [files('test-device-nodes.c')],
 
         [files('test-ether-addr-util.c')],
diff --git a/src/test/test-argv-util.c b/src/test/test-argv-util.c
new file mode 100644 (file)
index 0000000..26f6038
--- /dev/null
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <sched.h>
+#include <unistd.h>
+
+#if HAVE_VALGRIND_VALGRIND_H
+#  include <valgrind/valgrind.h>
+#endif
+
+#include "argv-util.h"
+#include "missing_sched.h"
+#include "process-util.h"
+#include "tests.h"
+#include "virt.h"
+
+static void test_rename_process_now(const char *p, int ret) {
+        _cleanup_free_ char *comm = NULL, *cmdline = NULL;
+        int r;
+
+        log_info("/* %s(%s) */", __func__, p);
+
+        r = rename_process(p);
+        assert_se(r == ret ||
+                  (ret == 0 && r >= 0) ||
+                  (ret > 0 && r > 0));
+
+        log_debug_errno(r, "rename_process(%s): %m", p);
+
+        if (r < 0)
+                return;
+
+#if HAVE_VALGRIND_VALGRIND_H
+        /* see above, valgrind is weird, we can't verify what we are doing here */
+        if (RUNNING_ON_VALGRIND)
+                return;
+#endif
+
+        assert_se(get_process_comm(0, &comm) >= 0);
+        log_debug("comm = <%s>", comm);
+        assert_se(strneq(comm, p, TASK_COMM_LEN-1));
+        /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the
+         * future. We'd only check the initial part, at least until we recompile, but this will still pass. */
+
+        r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline);
+        assert_se(r >= 0);
+        /* we cannot expect cmdline to be renamed properly without privileges */
+        if (geteuid() == 0) {
+                if (r == 0 && detect_container() > 0)
+                        log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline);
+                else {
+                        log_info("cmdline = <%s> (expected <%.*s>)", cmdline, (int) strlen("test-process-util"), p);
+
+                        bool skip = cmdline[0] == '"'; /* A shortcut to check if the string is quoted */
+
+                        assert_se(strneq(cmdline + skip, p, strlen("test-process-util")));
+                        assert_se(startswith(cmdline + skip, p));
+                }
+        } else
+                log_info("cmdline = <%s> (not verified)", cmdline);
+}
+
+static void test_rename_process_one(const char *p, int ret) {
+        siginfo_t si;
+        pid_t pid;
+
+        log_info("/* %s(%s) */", __func__, p);
+
+        pid = fork();
+        assert_se(pid >= 0);
+
+        if (pid == 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);
+}
+
+TEST(rename_process_multi) {
+        pid_t pid;
+
+        pid = fork();
+        assert_se(pid >= 0);
+
+        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;
+        }
+
+        /* 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) {
+        test_rename_process_one("foo", 1); /* should always fit */
+        test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
+        test_rename_process_one("1234567", 1); /* should always fit */
+}
+
+static int intro(void) {
+        log_show_color(true);
+        return EXIT_SUCCESS;
+}
+
+DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
index 49aca68c49bc3670c27a1a8a4d3439c633be95c3..6543c617c855d5bdfaab265143b5bebb937349e9 100644 (file)
@@ -11,7 +11,6 @@
 #include "macro.h"
 #include "module-util.h"
 #include "tests.h"
-#include "util.h"
 
 static int load_module(const char *mod_name) {
         _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL;
index 990eb1e2b674be23be4ee74a9a2a6422dd441f2f..a9b2f537ca0b934011e4c6c659150f5f890720b6 100644 (file)
@@ -524,108 +524,6 @@ TEST(get_process_cmdline_harder) {
         _exit(EXIT_SUCCESS);
 }
 
-static void test_rename_process_now(const char *p, int ret) {
-        _cleanup_free_ char *comm = NULL, *cmdline = NULL;
-        int r;
-
-        log_info("/* %s(%s) */", __func__, p);
-
-        r = rename_process(p);
-        assert_se(r == ret ||
-                  (ret == 0 && r >= 0) ||
-                  (ret > 0 && r > 0));
-
-        log_debug_errno(r, "rename_process(%s): %m", p);
-
-        if (r < 0)
-                return;
-
-#if HAVE_VALGRIND_VALGRIND_H
-        /* see above, valgrind is weird, we can't verify what we are doing here */
-        if (RUNNING_ON_VALGRIND)
-                return;
-#endif
-
-        assert_se(get_process_comm(0, &comm) >= 0);
-        log_debug("comm = <%s>", comm);
-        assert_se(strneq(comm, p, TASK_COMM_LEN-1));
-        /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the
-         * future. We'd only check the initial part, at least until we recompile, but this will still pass. */
-
-        r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline);
-        assert_se(r >= 0);
-        /* we cannot expect cmdline to be renamed properly without privileges */
-        if (geteuid() == 0) {
-                if (r == 0 && detect_container() > 0)
-                        log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline);
-                else {
-                        log_info("cmdline = <%s> (expected <%.*s>)", cmdline, (int) strlen("test-process-util"), p);
-
-                        bool skip = cmdline[0] == '"'; /* A shortcut to check if the string is quoted */
-
-                        assert_se(strneq(cmdline + skip, p, strlen("test-process-util")));
-                        assert_se(startswith(cmdline + skip, p));
-                }
-        } else
-                log_info("cmdline = <%s> (not verified)", cmdline);
-}
-
-static void test_rename_process_one(const char *p, int ret) {
-        siginfo_t si;
-        pid_t pid;
-
-        log_info("/* %s(%s) */", __func__, p);
-
-        pid = fork();
-        assert_se(pid >= 0);
-
-        if (pid == 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);
-}
-
-TEST(rename_process_multi) {
-        pid_t pid;
-
-        pid = fork();
-        assert_se(pid >= 0);
-
-        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;
-        }
-
-        /* 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) {
-        test_rename_process_one("foo", 1); /* should always fit */
-        test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
-        test_rename_process_one("1234567", 1); /* should always fit */
-}
-
 TEST(getpid_cached) {
         siginfo_t si;
         pid_t a, b, c, d, e, f, child;