process-util: introduce prctl_safe() and port everything over to it (#43006)

prctl() is an API full of pitfalls: it is variadic, and some interfaces
don't expect zero-initialization of excess arguments, and others do.
Moreover, the parameters are "long", and nonetheless we usually pass
"int" to them. If we are too dumb to call it properly, let's just not
call it directly anymore, but let's add a wrapper around it that makes
the function non-variadic and declares the right types. Then, let's port
over everything to it.

This is inspired by #42996, but we had issues with this many times,
before and looking at this PR one can see that we otherwise still are
having the issue at numerous other places.
This commit is contained in:
Luca Boccassi
2026-07-13 17:02:57 +01:00
committed by GitHub
23 changed files with 245 additions and 172 deletions
+22 -16
View 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;
@@ -182,6 +186,7 @@ static int update_argv(const char name[], size_t l) {
int rename_process_full(const char *comm, const char *invocation) {
bool truncated = false;
int r;
/* This is a like a poor man's setproctitle(). It changes the comm field by the name specified by
* 'comm', and changes argv[0] and the glibc's internally used names of the process
@@ -204,8 +209,9 @@ int rename_process_full(const char *comm, const char *invocation) {
/* 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, comm) < 0)
log_debug_errno(errno, "PR_SET_NAME failed: %m");
r = proc_set_comm(comm);
if (r < 0)
log_debug_errno(r, "PR_SET_NAME failed: %m");
if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */
truncated = true;
+30 -23
View 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);
}
+8 -13
View File
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sched.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -10,8 +8,8 @@
#include "errno-util.h"
#include "fd-util.h"
#include "memfd-util.h"
#include "process-util.h"
#include "string-util.h"
#include "utf8.h"
int memfd_create_wrapper(const char *name, unsigned mode) {
unsigned mode_compat;
@@ -36,26 +34,23 @@ int memfd_create_wrapper(const char *name, unsigned mode) {
int memfd_new_full(const char *name, unsigned extra_flags) {
_cleanup_free_ char *g = NULL;
int r;
if (!name) {
char pr[TASK_COMM_LEN] = {};
/* If no name is specified we generate one. We include
* a hint indicating our library implementation, and
* add the thread name to it */
assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
_cleanup_free_ char *comm = NULL;
r = pid_get_comm(/* pid= */ 0, &comm);
if (r < 0)
return r;
if (isempty(pr))
if (isempty(comm))
name = "sd";
else {
_cleanup_free_ char *e = NULL;
e = utf8_escape_invalid(pr);
if (!e)
return -ENOMEM;
g = strjoin("sd-", e);
g = strjoin("sd-", comm);
if (!g)
return -ENOMEM;
+46 -12
View 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;
}
@@ -2276,3 +2280,33 @@ int read_errno(int errno_fd) {
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received positive errno from child, refusing: %d", r);
}
int prctl_safe(int op, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
/* prctl(2) is a bit messy: it's a variadic function, defined with "unsigned long" arguments. This
* means that unless people explicitly cast it's quite likely they end up passing a shorter type even
* though unsigned long is required. And most of the time it might even kind of work, but not
* always. Moreover, some calls insist on all unused arguments being zeroed out, others don't
* care. Let's define this wrapper to enforce the right types, and that all arguments are always
* passed, to avoid this confusion. */
return RET_NERRNO(prctl(op, arg2, arg3, arg4, arg5));
}
int proc_set_comm(const char *comm) {
return prctl_safe(PR_SET_NAME, (unsigned long) comm, 0, 0, 0);
}
int proc_set_nnp(void) {
return prctl_safe(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
}
nsec_t proc_get_timerslack(void) {
int r;
r = prctl_safe(PR_GET_TIMERSLACK, 0, 0, 0, 0);
if (r < 0)
return NSEC_INFINITY;
return r;
}
+6
View File
@@ -255,3 +255,9 @@ int safe_mlockall(int flags);
_noreturn_ void report_errno_and_exit(int errno_fd, int error);
int read_errno(int errno_fd);
int prctl_safe(int op, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
int proc_set_comm(const char *comm);
int proc_set_nnp(void);
nsec_t proc_get_timerslack(void);
+1 -2
View File
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/capability.h>
#include <sys/prctl.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -66,7 +65,7 @@ static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", systemd_features);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture()));
static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string);
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", proc_get_timerslack());
static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "u", Hashmap *, hashmap_size);
static BUS_DEFINE_PROPERTY_GET_REF(property_get_set_size, "u", Set *, set_size);
static BUS_DEFINE_PROPERTY_GET(property_get_default_timeout_abort_usec, "t", Manager, manager_default_timeout_abort_usec);
+44 -31
View 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,17 +6481,21 @@ 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");
}
}
if (context_has_no_new_privileges(context))
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
if (context_has_no_new_privileges(context)) {
r = proc_set_nnp();
if (r < 0) {
*exit_status = EXIT_NO_NEW_PRIVILEGES;
return log_error_errno(errno, "Failed to disable new privileges: %m");
return log_error_errno(r, "Failed to disable new privileges: %m");
}
}
#if HAVE_SECCOMP
r = apply_address_families(context, params);
@@ -6613,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
+5 -3
View 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);
}
+10 -7
View 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>
@@ -2739,9 +2739,10 @@ static int initialize_runtime(
}
if (arg_no_new_privs) {
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
r = proc_set_nnp();
if (r < 0) {
*ret_error_message = "Failed to disable new privileges";
return log_struct_errno(LOG_EMERG, errno,
return log_struct_errno(LOG_EMERG, r,
LOG_MESSAGE("Failed to disable new privileges: %m"),
LOG_MESSAGE_ID(SD_MESSAGE_CORE_DISABLE_PRIVILEGES_STR));
}
@@ -2794,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);
@@ -3567,7 +3570,7 @@ static int run_systemd(int argc, char *argv[]) {
* reexecution we are then called 'systemd'. That is confusing, hence let's call us systemd
* right-away. */
program_invocation_short_name = systemd;
(void) prctl(PR_SET_NAME, systemd);
(void) proc_set_comm(systemd);
/* Save the original command line */
save_argc_argv(argc, argv);
+2 -3
View File
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/prctl.h>
#include "sd-bus.h"
#include "sd-varlink.h"
@@ -18,6 +16,7 @@
#include "manager.h"
#include "path-util.h"
#include "pidref.h"
#include "process-util.h"
#include "selinux-access.h"
#include "set.h"
#include "strv.h"
@@ -118,7 +117,7 @@ static int manager_context_build_json(sd_json_variant **ret, const char *name, v
JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogPreUSec", manager_get_watchdog(m, WATCHDOG_PRETIMEOUT)),
JSON_BUILD_PAIR_STRING_NON_EMPTY("RuntimeWatchdogPreGovernor", m->watchdog_pretimeout_governor),
JSON_BUILD_PAIR_STRING_NON_EMPTY("WatchdogDevice", watchdog_get_device()),
JSON_BUILD_PAIR_FINITE_USEC("TimerSlackNSec", (uint64_t) prctl(PR_GET_TIMERSLACK)),
JSON_BUILD_PAIR_FINITE_USEC("TimerSlackNSec", proc_get_timerslack()),
JSON_BUILD_PAIR_ENUM("DefaultOOMPolicy", oom_policy_to_string(m->defaults.oom_policy)),
SD_JSON_BUILD_PAIR_INTEGER("DefaultOOMScoreAdjust", m->defaults.oom_score_adjust),
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultRestrictSUIDSGID", m->defaults.restrict_suid_sgid),
+6 -5
View File
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sched.h>
#include <sys/prctl.h>
#include <unistd.h>
#include "sd-event.h"
@@ -81,8 +80,9 @@ int import_fork_tar_x(int tree_fd, int userns_fd, PidRef *ret_pid) {
if (r < 0)
log_debug_errno(r, "Failed to drop capabilities, ignoring: %m");
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
log_warning_errno(errno, "Failed to enable PR_SET_NO_NEW_PRIVS, ignoring: %m");
r = proc_set_nnp();
if (r < 0)
log_warning_errno(r, "Failed to enable PR_SET_NO_NEW_PRIVS, ignoring: %m");
if (tar_x(pipefd[0], tree_fd, flags) < 0)
_exit(EXIT_FAILURE);
@@ -141,8 +141,9 @@ int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid) {
if (r < 0)
log_debug_errno(r, "Failed to drop capabilities, ignoring: %m");
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
log_warning_errno(errno, "Failed to enable PR_SET_NO_NEW_PRIVS, ignoring: %m");
r = proc_set_nnp();
if (r < 0)
log_warning_errno(r, "Failed to enable PR_SET_NO_NEW_PRIVS, ignoring: %m");
if (tar_c(tree_fd, pipefd[1], /* filename= */ NULL, flags) < 0)
_exit(EXIT_FAILURE);
+8 -5
View 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>
@@ -18,15 +18,18 @@
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;
}
+16 -12
View 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"
@@ -90,14 +91,13 @@
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
#include "nspawn-stub-pid1.h"
#include "nspawn.h"
#include "nsresource.h"
#include "os-util.h"
#include "parse-helpers.h"
#include "osc-context.h"
#include "options.h"
#include "os-util.h"
#include "osc-context.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);
@@ -3593,9 +3594,11 @@ static int inner_child(
if (r < 0)
return log_error_errno(r, "Dropping capabilities failed: %m");
if (arg_no_new_privileges)
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
return log_error_errno(errno, "Failed to disable new privileges: %m");
if (arg_no_new_privileges) {
r = proc_set_nnp();
if (r < 0)
return log_error_errno(r, "Failed to disable new privileges: %m");
}
/* LXC sets container=lxc, so follow the scheme here */
envp[n_env++] = strjoina("container=", arg_container_service_name);
@@ -3961,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)
+1 -2
View File
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sched.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -64,7 +63,7 @@ int asynchronous_fsync(int fd, PidRef *ret_pid) {
static int close_func(void *p) {
unsigned v = PTR_TO_UINT(p);
(void) prctl(PR_SET_NAME, (unsigned long*) "(sd-close)");
(void) proc_set_comm("(sd-close)");
/* Note: 💣 This function is invoked in a child process created via glibc's clone() wrapper. In such
* children memory allocation is not allowed, since glibc does not release malloc mutexes in
+3 -3
View 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] = {
+5 -4
View File
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sched.h>
#include <sys/prctl.h>
#include "sd-varlink.h"
@@ -25,13 +24,15 @@
assert_cc(TASK_COMM_LEN == NAMESPACE_NAME_MAX);
static int make_pid_name(char **ret) {
char comm[TASK_COMM_LEN];
static uint64_t counter = 0;
int r;
assert(ret);
if (prctl(PR_GET_NAME, comm) < 0)
return -errno;
_cleanup_free_ char *comm = NULL;
r = pid_get_comm(0, &comm);
if (r < 0)
return r;
char spid[DECIMAL_STR_MAX(pid_t)];
xsprintf(spid, PID_FMT, getpid_cached());
+3 -4
View 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) {
+14 -12
View 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();
+3 -3
View 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;
}
+3 -3
View 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]);
+4 -5
View File
@@ -7,7 +7,6 @@
#include <sys/eventfd.h>
#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -175,7 +174,7 @@ static void test_pid_get_comm_escape_one(const char *input, const char *output)
log_debug("input: <%s> — output: <%s>", input, output);
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, input));
ASSERT_OK(proc_set_comm(input));
ASSERT_OK(pid_get_comm(0, &n));
log_debug("got: <%s>", n);
@@ -199,7 +198,7 @@ TEST(pid_get_comm_escape) {
test_pid_get_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237");
test_pid_get_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237");
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, saved));
ASSERT_OK(proc_set_comm(saved));
}
TEST(pid_is_unwaited) {
@@ -314,7 +313,7 @@ TEST(pid_get_cmdline_harder) {
ASSERT_OK_ERRNO(unlink(path));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "testa"));
ASSERT_OK(proc_set_comm("testa"));
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
@@ -477,7 +476,7 @@ TEST(pid_get_cmdline_harder) {
args = strv_free(args);
ASSERT_OK_ERRNO(ftruncate(fd, 0));
ASSERT_OK_ERRNO(prctl(PR_SET_NAME, "aaaa bbbb cccc"));
ASSERT_OK(proc_set_comm("aaaa bbbb cccc"));
ASSERT_ERROR(pid_get_cmdline(0, SIZE_MAX, 0, &line), ENOENT);
+3 -2
View 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) {
@@ -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;