tree-wide: port to prctl_safe()
This commit is contained in:
+18
-14
@@ -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;
|
||||
|
||||
+30
-23
@@ -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);
|
||||
}
|
||||
|
||||
+16
-12
@@ -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;
|
||||
}
|
||||
|
||||
+39
-28
@@ -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
|
||||
|
||||
+5
-3
@@ -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);
|
||||
}
|
||||
|
||||
+6
-4
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+11
-9
@@ -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);
|
||||
@@ -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)
|
||||
|
||||
@@ -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] = {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
+3
-2
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user