#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"
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
* 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)
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;
#include <stdatomic.h>
#include <stdio.h>
-#include <sys/prctl.h>
+#include <sys/prctl.h> /* IWYU pragma: keep */
#include <sys/syscall.h>
#include <unistd.h>
/* 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;
}
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);
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;
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;
}
/* 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 */
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);
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);
}
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;
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();
}
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. */
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) {
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;
}
#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>
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;
}
/* 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
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");
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:
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);
}
}
- 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)
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
/* 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.
*
*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 (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
#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>
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);
}
#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>
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);
/* 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;
}
#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>
#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"
/* 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);
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)
/* 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"
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] = {
#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>
}
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) {
#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
#include "fd-util.h"
#include "fileio.h"
#include "parse-util.h"
+#include "pidref.h"
#include "process-util.h"
#include "tests.h"
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;
}
}
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) {
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.");
}
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);
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();
#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"
* 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;
}
#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>
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]);
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]);
/* 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
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) {
#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>
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;