]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: port to prctl_safe() 43006/head
authorLennart Poettering <lennart@amutable.com>
Mon, 13 Jul 2026 08:12:46 +0000 (10:12 +0200)
committerLennart Poettering <lennart@amutable.com>
Mon, 13 Jul 2026 13:39:17 +0000 (15:39 +0200)
15 files changed:
src/basic/argv-util.c
src/basic/capability-util.c
src/basic/process-util.c
src/core/exec-invoke.c
src/core/execute.c
src/core/main.c
src/nspawn/nspawn-stub-pid1.c
src/nspawn/nspawn.c
src/shared/coredump-util.c
src/shared/seccomp-util.c
src/test/test-capability-util.c
src/test/test-execute.c
src/test/test-namespace.c
src/test/test-thp.c
src/tty-ask-password-agent/tty-ask-password-agent.c

index 68cdea11aecd28db742b07b376d82815a9d42fee..20587f66ada203ec0b907674d51ac34beb5323f1 100644 (file)
@@ -3,7 +3,7 @@
 #include <sched.h>
 #include <stdlib.h>
 #include <sys/mman.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 
 #include "argv-util.h"
 #include "capability-util.h"
@@ -133,10 +133,10 @@ static int update_argv(const char name[], size_t l) {
                 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");
-
+                r = prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0);
+                if (ERRNO_IS_NEG_PRIVILEGE(r))
+                        return log_debug_errno(r, "PR_SET_MM_ARG_START failed: %m");
+                if (r < 0) {
                         /* 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
@@ -145,22 +145,25 @@ static int update_argv(const char name[], size_t l) {
                          * 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");
+                        log_debug_errno(r, "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");
+                        r = prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0);
+                        if (r < 0) {
+                                log_debug_errno(r, "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");
+                        r = prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0);
+                        if (r < 0)
+                                return log_debug_errno(r, "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");
+                        r = prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0);
+                        if (r < 0)
+                                log_debug_errno(r, "PR_SET_MM_ARG_END failed, proceeding without: %m");
                 }
 
                 if (mm)
@@ -172,8 +175,9 @@ static int update_argv(const char name[], size_t l) {
                 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");
+                r = prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) mm + l + 1, 0, 0);
+                if (r < 0)
+                        log_debug_errno(r, "PR_SET_MM_ARG_END failed, proceeding without: %m");
         }
 
         can_do = true;
index 29434dc2ea44d6e0ffb4965381f6349869742c27..18942d4c3616d79f264e9a8cdf91bd6f9a3b1ed1 100644 (file)
@@ -2,7 +2,7 @@
 
 #include <stdatomic.h>
 #include <stdio.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/syscall.h>
 #include <unistd.h>
 
@@ -100,18 +100,18 @@ unsigned cap_last_cap(void) {
         /* Fall back to syscall-probing for pre linux-3.2, or where /proc/ is not mounted */
         unsigned long p = (unsigned long) MIN(CAP_LAST_CAP, CAP_LIMIT);
 
-        if (prctl(PR_CAPBSET_READ, p) < 0) {
+        if (prctl_safe(PR_CAPBSET_READ, p, 0, 0, 0) < 0) {
 
                 /* Hmm, look downwards, until we find one that works */
                 for (p--; p > 0; p--)
-                        if (prctl(PR_CAPBSET_READ, p) >= 0)
+                        if (prctl_safe(PR_CAPBSET_READ, p, 0, 0, 0) >= 0)
                                 break;
 
         } else {
 
                 /* Hmm, look upwards, until we find one that doesn't work */
                 for (; p < CAP_LIMIT; p++)
-                        if (prctl(PR_CAPBSET_READ, p+1) < 0)
+                        if (prctl_safe(PR_CAPBSET_READ, p+1, 0, 0, 0) < 0)
                                 break;
         }
 
@@ -154,7 +154,10 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
                 if (!BIT_SET(set, i))
                         continue;
 
-                if (prctl(PR_CAPBSET_READ, (unsigned long) i) != 1) {
+                r = prctl_safe(PR_CAPBSET_READ, i, 0, 0, 0);
+                if (r < 0)
+                        return r;
+                if (r != 1) {
                         log_debug("Ambient capability %s requested but missing from bounding set, suppressing automatically.",
                                   capability_to_name(i));
                         CLEAR_BIT(set, i);
@@ -180,16 +183,19 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
         for (unsigned i = 0; i <= cap_last_cap(); i++)
                 if (BIT_SET(set, i)) {
                         /* Add the capability to the ambient set. */
-                        if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0)
-                                return -errno;
+                        r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0);
+                        if (r < 0)
+                                return r;
                 } else {
                         /* Drop the capability so we don't inherit capabilities we didn't ask for. */
-                        r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
+                        r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
                         if (r < 0)
-                                return -errno;
-                        if (r > 0)
-                                if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, i, 0, 0) < 0)
-                                        return -errno;
+                                return r;
+                        if (r > 0) {
+                                r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, i, 0, 0);
+                                if (r < 0)
+                                        return r;
+                        }
                 }
 
         return 0;
@@ -241,13 +247,12 @@ int capability_bounding_set_drop(uint64_t keep, bool right_now) {
                         continue;
 
                 /* Drop it from the bounding set */
-                if (prctl(PR_CAPBSET_DROP, i) < 0) {
-                        r = -errno;
-
+                r = prctl_safe(PR_CAPBSET_DROP, i, 0, 0, 0);
+                if (r < 0) {
                         /* If dropping the capability failed, let's see if we didn't have it in the first
                          * place. If so, continue anyway, as dropping a capability we didn't have in the
                          * first place doesn't really matter anyway. */
-                        if (prctl(PR_CAPBSET_READ, i) != 0)
+                        if (prctl_safe(PR_CAPBSET_READ, i, 0, 0, 0) != 0)
                                 goto finish;
                 }
 
@@ -332,14 +337,16 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
         /* Ensure we keep the permitted caps across the setresuid(). Note that we do this even if we actually
          * don't want to keep any capabilities, since we want to be able to drop them from the bounding set
          * too, and we can only do that if we have capabilities. */
-        if (prctl(PR_SET_KEEPCAPS, 1) < 0)
-                return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
+        r = prctl_safe(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to enable keep capabilities flag: %m");
 
         if (setresuid(uid, uid, uid) < 0)
                 return log_error_errno(errno, "Failed to change user ID: %m");
 
-        if (prctl(PR_SET_KEEPCAPS, 0) < 0)
-                return log_error_errno(errno, "Failed to disable keep capabilities flag: %m");
+        r = prctl_safe(PR_SET_KEEPCAPS, 0, 0, 0, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to disable keep capabilities flag: %m");
 
         /* Drop all caps from the bounding set (as well as the inheritable/permitted/effective sets), except
          * the ones we want to keep */
@@ -404,7 +411,7 @@ bool capability_quintet_mangle(CapabilityQuintet *q) {
                 if (!BIT_SET(combined, i))
                         continue;
 
-                if (prctl(PR_CAPBSET_READ, (unsigned long) i) > 0)
+                if (prctl_safe(PR_CAPBSET_READ, i, 0, 0, 0) > 0)
                         continue;
 
                 SET_BIT(drop, i);
@@ -515,9 +522,9 @@ int capability_get_ambient(uint64_t *ret) {
         assert(ret);
 
         for (unsigned i = 0; i <= cap_last_cap(); i++) {
-                r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
+                r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
                 if (r < 0)
-                        return -errno;
+                        return r;
                 if (r > 0)
                         SET_BIT(a, i);
         }
index e342de287b2bb8c9ee4cb894cb90ef9c92d69438..ab563c51058822e2ef07b71a46c61cc588d435cd 100644 (file)
@@ -104,8 +104,9 @@ int pid_get_comm(pid_t pid, char **ret) {
                 if (!comm)
                         return -ENOMEM;
 
-                if (prctl(PR_GET_NAME, comm) < 0)
-                        return -errno;
+                r = prctl_safe(PR_GET_NAME, (unsigned long) comm, 0, 0, 0);
+                if (r < 0)
+                        return r;
         } else {
                 const char *p;
 
@@ -1572,11 +1573,13 @@ int pidref_safe_fork_full(
         if (!FLAGS_SET(flags, FORK_ALLOW_DLOPEN))
                 block_dlopen();
 
-        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL))
-                if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) {
-                        log_full_errno(prio, errno, "Failed to set death signal: %m");
+        if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL)) {
+                r = prctl_safe(PR_SET_PDEATHSIG, fork_flags_to_signal(flags), 0, 0, 0);
+                if (r < 0) {
+                        log_full_errno(prio, r, "Failed to set death signal: %m");
                         _exit(EXIT_FAILURE);
                 }
+        }
 
         if (flags & FORK_RESET_SIGNALS) {
                 r = reset_all_signal_handlers();
@@ -1978,7 +1981,7 @@ int get_process_threads(pid_t pid) {
 }
 
 int is_reaper_process(void) {
-        int b = 0;
+        int b = 0, r;
 
         /* Checks if we are running in a reaper process, i.e. if we are expected to deal with processes
          * reparented to us. This simply checks if we are PID 1 or if PR_SET_CHILD_SUBREAPER was called. */
@@ -1986,13 +1989,15 @@ int is_reaper_process(void) {
         if (getpid_cached() == 1)
                 return true;
 
-        if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0)
-                return -errno;
+        r = prctl_safe(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0, 0, 0);
+        if (r < 0)
+                return r;
 
         return b != 0;
 }
 
 int make_reaper_process(bool b) {
+        int r;
 
         if (getpid_cached() == 1) {
 
@@ -2002,10 +2007,9 @@ int make_reaper_process(bool b) {
                 return 0;
         }
 
-        /* Some prctl()s insist that all 5 arguments are specified, others do not. Let's always specify all,
-         * to avoid any ambiguities */
-        if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long) b, 0UL, 0UL, 0UL) < 0)
-                return -errno;
+        r = prctl_safe(PR_SET_CHILD_SUBREAPER, b, 0, 0, 0);
+        if (r < 0)
+                return r;
 
         return 0;
 }
index 81ca984111a2cfe93e2b8231145437026ea1d994..0faedf3dc1c5d349e551290ce04f2277ed4f1a82 100644 (file)
@@ -9,7 +9,7 @@
 #include <sys/ioprio.h>
 #include <sys/keyctl.h>
 #include <sys/mount.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/statvfs.h>
 #include <unistd.h>
 
@@ -983,19 +983,20 @@ static int enforce_groups(gid_t gid, const gid_t *supplementary_gids, int ngids)
 
 static int set_securebits(unsigned bits, unsigned mask) {
         unsigned applied;
-        int current;
+        int current, r;
 
-        current = prctl(PR_GET_SECUREBITS);
+        current = prctl_safe(PR_GET_SECUREBITS, 0, 0, 0, 0);
         if (current < 0)
-                return -errno;
+                return current;
 
         /* Clear all securebits defined in mask and set bits */
         applied = ((unsigned) current & ~mask) | bits;
         if ((unsigned) current == applied)
                 return 0;
 
-        if (prctl(PR_SET_SECUREBITS, applied) < 0)
-                return -errno;
+        r = prctl_safe(PR_SET_SECUREBITS, applied, 0, 0, 0);
+        if (r < 0)
+                return r;
 
         return 1;
 }
@@ -1408,7 +1409,8 @@ static int setup_pam(
                 /* Wait until our parent died. This will only work if the above setresuid() succeeds,
                  * otherwise the kernel will not allow unprivileged parents kill their privileged children
                  * this way. We rely on the control groups kill logic to do the rest for us. */
-                if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+                r = prctl_safe(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);
+                if (r < 0)
                         goto child_finish;
 
                 /* Tell the parent that our setup is done. This is especially important regarding dropping
@@ -1714,13 +1716,13 @@ static int apply_memory_deny_write_execute(const ExecContext *c, const ExecParam
                 return 0;
 
         /* use prctl() if kernel supports it (6.3) */
-        r = prctl(PR_SET_MDWE, PR_MDWE_REFUSE_EXEC_GAIN, 0, 0, 0);
+        r = prctl_safe(PR_SET_MDWE, PR_MDWE_REFUSE_EXEC_GAIN, 0, 0, 0);
         if (r == 0) {
                 log_debug("Enabled MemoryDenyWriteExecute= with PR_SET_MDWE");
                 return 0;
         }
-        if (r < 0 && errno != EINVAL)
-                return log_debug_errno(errno, "Failed to enable MemoryDenyWriteExecute= with PR_SET_MDWE: %m");
+        if (r < 0 && r != -EINVAL)
+                return log_debug_errno(r, "Failed to enable MemoryDenyWriteExecute= with PR_SET_MDWE: %m");
         /* else use seccomp */
         log_debug("Kernel doesn't support PR_SET_MDWE: falling back to seccomp");
 
@@ -4850,15 +4852,15 @@ static int set_memory_thp(ExecMemoryTHP thp) {
                 return 0;
 
         case EXEC_MEMORY_THP_DISABLE:
-                r = RET_NERRNO(prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0));
+                r = prctl_safe(PR_SET_THP_DISABLE, 1, 0, 0, 0);
                 break;
 
         case EXEC_MEMORY_THP_MADVISE:
-                r = RET_NERRNO(prctl(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, 0, 0));
+                r = prctl_safe(PR_SET_THP_DISABLE, 1, PR_THP_DISABLE_EXCEPT_ADVISED, 0, 0);
                 break;
 
         case EXEC_MEMORY_THP_SYSTEM:
-                r = RET_NERRNO(prctl(PR_SET_THP_DISABLE, 0, 0, 0, 0));
+                r = prctl_safe(PR_SET_THP_DISABLE, 0, 0, 0, 0);
                 break;
 
         default:
@@ -5658,11 +5660,13 @@ int exec_invoke(
                         return log_error_errno(errno, "Failed to set up IO scheduling priority: %m");
                 }
 
-        if (context->timer_slack_nsec != NSEC_INFINITY)
-                if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
+        if (context->timer_slack_nsec != NSEC_INFINITY) {
+                r = prctl_safe(PR_SET_TIMERSLACK, context->timer_slack_nsec, 0, 0, 0);
+                if (r < 0) {
                         *exit_status = EXIT_TIMERSLACK;
-                        return log_error_errno(errno, "Failed to set up timer slack: %m");
+                        return log_error_errno(r, "Failed to set up timer slack: %m");
                 }
+        }
 
         if (context->personality != PERSONALITY_INVALID) {
                 r = safe_personality(context->personality);
@@ -5672,15 +5676,17 @@ int exec_invoke(
                 }
         }
 
-        if (context->memory_ksm >= 0)
-                if (prctl(PR_SET_MEMORY_MERGE, context->memory_ksm, 0, 0, 0) < 0) {
-                        if (ERRNO_IS_NOT_SUPPORTED(errno))
-                                log_debug_errno(errno, "KSM support not available, ignoring.");
+        if (context->memory_ksm >= 0) {
+                r = prctl_safe(PR_SET_MEMORY_MERGE, context->memory_ksm, 0, 0, 0);
+                if (r < 0) {
+                        if (ERRNO_IS_NOT_SUPPORTED(r))
+                                log_debug_errno(r, "KSM support not available, ignoring.");
                         else {
                                 *exit_status = EXIT_KSM;
-                                return log_error_errno(errno, "Failed to set KSM: %m");
+                                return log_error_errno(r, "Failed to set KSM: %m");
                         }
                 }
+        }
 
         r = set_memory_thp(context->memory_thp);
         if (r == -EOPNOTSUPP)
@@ -6321,9 +6327,10 @@ int exec_invoke(
                     seccomp_allows_drop_privileges(context)) {
                         keep_seccomp_privileges = true;
 
-                        if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+                        r = prctl_safe(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+                        if (r < 0) {
                                 *exit_status = EXIT_USER;
-                                return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
+                                return log_error_errno(r, "Failed to enable keep capabilities flag: %m");
                         }
 
                         /* Save the current bounding set so we can restore it after applying the seccomp
@@ -6456,7 +6463,8 @@ int exec_invoke(
                 /* PR_GET_SECUREBITS is not privileged, while PR_SET_SECUREBITS is. So to suppress potential
                  * EPERMs we'll try not to call PR_SET_SECUREBITS unless necessary. Setting securebits
                  * requires CAP_SETPCAP. */
-                if (prctl(PR_GET_SECUREBITS) != secure_bits) {
+                r = prctl_safe(PR_GET_SECUREBITS, 0, 0, 0, 0);
+                if (r != secure_bits) {
                         /* CAP_SETPCAP is required to set securebits. This capability is raised into the
                          * effective set here.
                          *
@@ -6473,9 +6481,11 @@ int exec_invoke(
                                 *exit_status = EXIT_CAPABILITIES;
                                 return log_error_errno(r, "Failed to gain CAP_SETPCAP for setting secure bits");
                         }
-                        if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) {
+
+                        r = prctl_safe(PR_SET_SECUREBITS, secure_bits, 0, 0, 0);
+                        if (r < 0) {
                                 *exit_status = EXIT_SECUREBITS;
-                                return log_error_errno(errno, "Failed to set process secure bits: %m");
+                                return log_error_errno(r, "Failed to set process secure bits: %m");
                         }
                 }
 
@@ -6615,9 +6625,10 @@ int exec_invoke(
                                 }
                         }
 
-                        if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
+                        r = prctl_safe(PR_SET_KEEPCAPS, 0, 0, 0, 0);
+                        if (r < 0) {
                                 *exit_status = EXIT_USER;
-                                return log_error_errno(errno, "Failed to drop keep capabilities flag: %m");
+                                return log_error_errno(r, "Failed to drop keep capabilities flag: %m");
                         }
                 }
 #endif
index f581b5c120ba1b9ee34448c46d477cb650d3c45c..8eb505d4fb4c38207a80bf4d86b63c7fad32779b 100644 (file)
@@ -4,7 +4,7 @@
 #include <poll.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -1972,9 +1972,11 @@ uint64_t exec_context_get_timer_slack_nsec(const ExecContext *c) {
         if (c->timer_slack_nsec != NSEC_INFINITY)
                 return c->timer_slack_nsec;
 
-        r = prctl(PR_GET_TIMERSLACK);
-        if (r < 0)
+        r = prctl_safe(PR_GET_TIMERSLACK, 0, 0, 0, 0);
+        if (r < 0) {
                 log_debug_errno(r, "Failed to get timer slack, ignoring: %m");
+                return 0;
+        }
 
         return (uint64_t) MAX(r, 0);
 }
index 663b6d6f5f89d335486ad320c7893ca9d05ccd0b..c952472e7333c247fb4be8c67269fd16adcb392a 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/vt.h>
 #include <stdlib.h>
 #include <sys/mount.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/utsname.h>
 #include <unistd.h>
 
@@ -2795,9 +2795,11 @@ static int initialize_runtime(
         if (r < 0)
                 log_warning_errno(r, "Failed to reset ambient capability set, ignoring: %m");
 
-        if (arg_timer_slack_nsec != NSEC_INFINITY)
-                if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
-                        log_warning_errno(errno, "Failed to adjust timer slack, ignoring: %m");
+        if (arg_timer_slack_nsec != NSEC_INFINITY) {
+                r = prctl_safe(PR_SET_TIMERSLACK, arg_timer_slack_nsec, 0, 0, 0);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to adjust timer slack, ignoring: %m");
+        }
 
         if (arg_syscall_archs) {
                 r = enforce_syscall_archs(arg_syscall_archs);
index 6a64aea5115fa9301ffe94c957114ac77ce63500..2ed7bcffd4b81d512e8b3ba5a22753fc89a823ed 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <sys/ioctl.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/reboot.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
 static int reset_environ(const char *new_environment, size_t length) {
         unsigned long start, end;
+        int r;
 
         start = (unsigned long) new_environment;
         end = start + length;
 
-        if (prctl(PR_SET_MM, PR_SET_MM_ENV_START, start, 0, 0) < 0)
-                return -errno;
+        r = prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, start, 0, 0);
+        if (r < 0)
+                return r;
 
-        if (prctl(PR_SET_MM, PR_SET_MM_ENV_END, end, 0, 0) < 0)
-                return -errno;
+        r = prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, end, 0, 0);
+        if (r < 0)
+                return r;
 
         return 0;
 }
index 13d54364157ed54a4037ea396678bc45875e9be8..a2e0d31de7dfb664f30f1e23b5f02cbcec154a40 100644 (file)
@@ -8,7 +8,7 @@
 #include <sys/keyctl.h>
 #include <sys/mount.h>
 #include <sys/personality.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -79,6 +79,7 @@
 #include "namespace-util.h"
 #include "netlink-internal.h"
 #include "notify-recv.h"
+#include "nspawn.h"
 #include "nspawn-bind-user.h"
 #include "nspawn-cgroup.h"
 #include "nspawn-expose-ports.h"
 #include "nspawn-settings.h"
 #include "nspawn-setuid.h"
 #include "nspawn-stub-pid1.h"
-#include "nspawn.h"
 #include "nsresource.h"
+#include "options.h"
 #include "os-util.h"
-#include "parse-helpers.h"
 #include "osc-context.h"
-#include "options.h"
 #include "pager.h"
 #include "parse-argument.h"
+#include "parse-helpers.h"
 #include "parse-util.h"
 #include "path-lookup.h"
 #include "path-util.h"
@@ -3579,8 +3579,9 @@ static int inner_child(
 
         /* Make sure we keep the caps across the uid/gid dropping, so that we can retain some selected caps
          * if we need to later on. */
-        if (prctl(PR_SET_KEEPCAPS, 1) < 0)
-                return log_error_errno(errno, "Failed to set PR_SET_KEEPCAPS: %m");
+        r = prctl_safe(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set PR_SET_KEEPCAPS: %m");
 
         if (uid_is_valid(arg_uid) || gid_is_valid(arg_gid))
                 r = change_uid_gid_raw(arg_uid, arg_gid, arg_supplementary_gids, arg_n_supplementary_gids, arg_console_mode != CONSOLE_PIPE);
@@ -3963,8 +3964,9 @@ static int outer_child(
         if (r < 0)
                 log_debug_errno(r, "Failed to read os-release from host for container, ignoring: %m");
 
-        if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
-                return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
+        r = prctl_safe(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
+        if (r < 0)
+                return log_error_errno(r, "PR_SET_PDEATHSIG failed: %m");
 
         r = reset_audit_loginuid();
         if (r < 0)
index d979de17768dc8934ad32bc73baa8e7e2989f6e3..894cf3869ba2e28d4858b6b023b443d4cd54a644 100644 (file)
@@ -1,15 +1,15 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <elf.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 
 #include "alloc-util.h"
 #include "coredump-util.h"
-#include "errno-util.h"
 #include "extract-word.h"
 #include "fileio.h"
 #include "log.h"
 #include "parse-util.h"
+#include "process-util.h"
 #include "stdio-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -18,7 +18,7 @@
 
 int set_dumpable(SuidDumpMode mode) {
         /* Cast mode explicitly to long, because prctl wants longs but is varargs. */
-        return RET_NERRNO(prctl(PR_SET_DUMPABLE, (long) mode));
+        return prctl_safe(PR_SET_DUMPABLE, mode, 0, 0, 0);
 }
 
 static const char *const coredump_filter_table[_COREDUMP_FILTER_MAX] = {
index 2a8995666feeae2368f999dc5c4e7720f44a10a2..cf65e1ca0ed26b159fff6d74a5f0a0b513da1074 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/seccomp.h>
 #include <sched.h>
 #include <sys/mman.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/shm.h>
 #include <sys/stat.h>
 
@@ -301,12 +301,11 @@ int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_
 }
 
 static bool is_basic_seccomp_available(void) {
-        return prctl(PR_GET_SECCOMP, 0, 0, 0, 0) >= 0;
+        return prctl_safe(PR_GET_SECCOMP, 0, 0, 0, 0) >= 0;
 }
 
 static bool is_seccomp_filter_available(void) {
-        return prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0) < 0 &&
-                errno == EFAULT;
+        return prctl_safe(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, 0, 0, 0) == -EFAULT;
 }
 
 bool is_seccomp_available(void) {
index cd536dd4cb6cf56ec53177782b216cc7a247b2ce..ccf73d2bbfd4ca977b9f2408282765781dc2dda2 100644 (file)
@@ -3,10 +3,9 @@
 #include <netinet/in.h>
 #include <pwd.h>
 #include <stdlib.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/socket.h>
 #include <unistd.h>
-#include "pidref.h"
 
 #define TEST_CAPABILITY_C
 
@@ -17,6 +16,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "parse-util.h"
+#include "pidref.h"
 #include "process-util.h"
 #include "tests.h"
 
@@ -64,13 +64,13 @@ TEST(last_cap_file) {
 TEST(last_cap_probe) {
         unsigned long p = (unsigned long)CAP_LAST_CAP;
 
-        if (prctl(PR_CAPBSET_READ, p) < 0) {
+        if (prctl_safe(PR_CAPBSET_READ, p, 0, 0, 0) < 0) {
                 for (p--; p > 0; p--)
-                        if (prctl(PR_CAPBSET_READ, p) >= 0)
+                        if (prctl_safe(PR_CAPBSET_READ, p, 0, 0, 0) >= 0)
                                 break;
         } else {
                 for (;; p++)
-                        if (prctl(PR_CAPBSET_READ, p+1) < 0)
+                        if (prctl_safe(PR_CAPBSET_READ, p+1, 0, 0, 0) < 0)
                                 break;
         }
 
@@ -180,17 +180,17 @@ TEST(have_effective_cap) {
 }
 
 static void test_apply_ambient_caps_impl(void) {
-        ASSERT_OK_EQ_ERRNO(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0), 0);
+        ASSERT_OK_ZERO(prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0));
 
         ASSERT_OK(capability_ambient_set_apply(UINT64_C(1) << CAP_CHOWN, /* also_inherit= */ true));
         ASSERT_OK_POSITIVE(have_inheritable_cap(CAP_CHOWN));
 
-        ASSERT_OK_EQ_ERRNO(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0), 1);
+        ASSERT_OK_EQ(prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0), 1);
 
         ASSERT_OK(capability_ambient_set_apply(0, /* also_inherit= */ true));
         ASSERT_OK_ZERO(have_inheritable_cap(CAP_CHOWN));
 
-        ASSERT_OK_EQ_ERRNO(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0), 0);
+        ASSERT_OK_ZERO(prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0));
 }
 
 TEST(apply_ambient_caps) {
@@ -234,10 +234,10 @@ TEST(capability_get_ambient) {
 
         ASSERT_OK(capability_get_ambient(&c));
 
-        r = prctl(PR_CAPBSET_READ, CAP_MKNOD);
+        r = prctl_safe(PR_CAPBSET_READ, CAP_MKNOD, 0, 0, 0);
         if (r <= 0)
                 return (void) log_tests_skipped("Lacking CAP_MKNOD, skipping getambient test.");
-        r = prctl(PR_CAPBSET_READ, CAP_LINUX_IMMUTABLE);
+        r = prctl_safe(PR_CAPBSET_READ, CAP_LINUX_IMMUTABLE, 0, 0, 0);
         if (r <= 0)
                 return (void) log_tests_skipped("Lacking CAP_LINUX_IMMUTABLE, skipping getambient test.");
 
@@ -303,6 +303,8 @@ TEST(pidref_get_capability) {
 }
 
 static int intro(void) {
+        int r;
+
         /* Try to set up nobody user/ambient caps for tests that need them.
          * Not finding nobody is non-fatal — those tests will skip themselves. */
         struct passwd *nobody = getpwnam(NOBODY_USER_NAME);
@@ -311,10 +313,10 @@ static int intro(void) {
                 test_gid = nobody->pw_gid;
         }
 
-        int r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+        r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
         /* There's support for PR_CAP_AMBIENT if the prctl() call succeeded or error code was something else
          * than EINVAL. The EINVAL check should be good enough to rule out false positives. */
-        run_ambient = r >= 0 || errno != EINVAL;
+        run_ambient = r >= 0 || r != -EINVAL;
 
         if (getuid() == 0)
                 show_capabilities();
index 8206452f4cefa58a04cc85d91ccd740897b575a7..9725fa0bf56bc761564e2ac0671f547d81bcb5ea 100644 (file)
@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mount.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <unistd.h>
 
 #include "sd-event.h"
@@ -1195,8 +1195,8 @@ static void test_exec_ambientcapabilities(Manager *m) {
          * the tests only if that's the case. Clearing all ambient
          * capabilities is fine, since we are expecting them to be unset
          * in the first place for the tests. */
-        r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
-        if (r < 0 && IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS)) {
+        r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+        if (r < 0 && IN_SET(r, -EINVAL, -EOPNOTSUPP, -ENOSYS)) {
                 log_notice("Skipping %s, the kernel does not support ambient capabilities", __func__);
                 return;
         }
index 41c67a3cf958bd75914ff34dc57fc1920ee0d021..b9f4e35f2e1a209833a16ab7f95a1b3738001502 100644 (file)
@@ -5,7 +5,7 @@
 #include <sched.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sysexits.h>
@@ -363,7 +363,7 @@ TEST(process_is_owned_by_uid) {
                 ASSERT_OK(fully_set_uid_gid(1, 1, NULL, 0));
 
                 /* After successfully changing id/gid DEATHSIG is reset, so it has to be set again */
-                ASSERT_OK_ERRNO(prctl(PR_SET_PDEATHSIG, SIGKILL));
+                ASSERT_OK(prctl_safe(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0));
 
                 ASSERT_OK_EQ_ERRNO(write(p[1], &(const char[]) { 'x' }, 1), 1);
                 p[1] = safe_close(p[1]);
@@ -401,7 +401,7 @@ TEST(process_is_owned_by_uid) {
                 ASSERT_OK(reset_uid_gid());
 
                 /* After successfully changing id/gid DEATHSIG is reset, so it has to be set again */
-                ASSERT_OK_ERRNO(prctl(PR_SET_PDEATHSIG, SIGKILL));
+                ASSERT_OK(prctl_safe(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0));
 
                 ASSERT_OK_EQ_ERRNO(write(p[1], &(const char[]) { 'x' }, 1), 1);
                 p[1] = safe_close(p[1]);
index 047bd26e8944ea84573f5586146274d2b0b1fc94..843c3c85602c539c02a5e7ffe498c66d4c87c258 100644 (file)
@@ -1,7 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 
+#include "process-util.h"
 #include "tests.h"
 
 #define PR_THP_DISABLE_NOT_SET 0
@@ -12,7 +13,7 @@ static const char *arg_mode = NULL;
 static int intro(void) {
         int r;
 
-        r = prctl(PR_GET_THP_DISABLE, 0, 0, 0, 0);
+        r = prctl_safe(PR_GET_THP_DISABLE, 0, 0, 0, 0);
         if (streq_ptr(arg_mode, "no-disable")) {
                 /* Test case: THPs should not be disabled */
                 if (r != PR_THP_DISABLE_NOT_SET) {
index d57ade56c9e7bf8d4e6a307127abb51eb1767b91..c725ef66a8ba2e2de71e70ff0d0f3abff58fddae 100644 (file)
@@ -6,7 +6,7 @@
 #include <fcntl.h>
 #include <poll.h>
 #include <stdlib.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
 #include <sys/signalfd.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
@@ -560,7 +560,7 @@ static int ask_on_this_console(const char *tty, char **arguments, PidRef *ret) {
         if (r < 0)
                 return r;
         if (r == 0) {
-                assert_se(prctl(PR_SET_PDEATHSIG, SIGHUP) >= 0);
+                assert_se(prctl_safe(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0) >= 0);
 
                 STRV_FOREACH(i, arguments) {
                         char *k;