tree-wide: remove support for kernels lacking ambient caps

Let's bump the kernel baseline a bit to 4.3 and thus require ambient
caps.

This allows us to remove support for a variety of special casing, most
importantly the ExecStart=!! hack.
This commit is contained in:
Lennart Poettering
2024-12-17 17:34:46 +01:00
parent 96ec3911f3
commit 00a415fc8f
18 changed files with 70 additions and 134 deletions
+1 -2
View File
@@ -1458,8 +1458,7 @@ static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) {
return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "",
FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "",
FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "",
FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "",
FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC) ? "!!" : "");
FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "");
}
int bus_set_transient_exec_command(
+16 -41
View File
@@ -1407,7 +1407,7 @@ static bool skip_seccomp_unavailable(const ExecContext *c, const ExecParameters
return true;
}
static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p, bool needs_ambient_hack) {
static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p) {
uint32_t negative_action, default_action, action;
int r;
@@ -1430,12 +1430,6 @@ static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p, b
action = negative_action;
}
if (needs_ambient_hack) {
r = seccomp_filter_set_add(c->syscall_filter, c->syscall_allow_list, syscall_filter_sets + SYSCALL_FILTER_SET_SETUID);
if (r < 0)
return r;
}
/* Sending over exec_fd or handoff_timestamp_fd requires write() syscall. */
if (p->exec_fd >= 0 || p->handoff_timestamp_fd >= 0) {
r = seccomp_filter_set_add_by_name(c->syscall_filter, c->syscall_allow_list, "write");
@@ -4297,8 +4291,7 @@ int exec_invoke(
bool userns_set_up = false;
bool needs_sandboxing, /* Do we need to set up full sandboxing? (i.e. all namespacing, all MAC stuff, caps, yadda yadda */
needs_setuid, /* Do we need to do the actual setresuid()/setresgid() calls? */
needs_mount_namespace, /* Do we need to set up a mount namespace for this kernel? */
needs_ambient_hack; /* Do we need to apply the ambient capabilities hack? */
needs_mount_namespace; /* Do we need to set up a mount namespace for this kernel? */
bool keep_seccomp_privileges = false;
bool has_cap_sys_admin = false;
#if HAVE_SELINUX
@@ -4939,17 +4932,9 @@ int exec_invoke(
return log_exec_error_errno(context, params, r, "Failed to set up kernel keyring: %m");
}
/* We need the ambient capability hack, if the caller asked us to apply it and the command is marked
* for it, and the kernel doesn't actually support ambient caps. */
needs_ambient_hack = (params->flags & EXEC_APPLY_SANDBOXING) && (command->flags & EXEC_COMMAND_AMBIENT_MAGIC) && !ambient_capabilities_supported();
/* We need setresuid() if the caller asked us to apply sandboxing and the command isn't explicitly
* excepted from either whole sandboxing or just setresuid() itself, and the ambient hack is not
* desired. */
if (needs_ambient_hack)
needs_setuid = false;
else
needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID));
* excepted from either whole sandboxing or just setresuid() itself. */
needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID));
uint64_t capability_ambient_set = context->capability_ambient_set;
@@ -4996,20 +4981,17 @@ int exec_invoke(
return log_exec_error_errno(context, params, r, "Failed to set up PAM session: %m");
}
if (ambient_capabilities_supported()) {
uint64_t ambient_after_pam;
/* PAM modules might have set some ambient caps. Query them here and merge them into
* the caps we want to set in the end, so that we don't end up unsetting them. */
r = capability_get_ambient(&ambient_after_pam);
if (r < 0) {
*exit_status = EXIT_CAPABILITIES;
return log_exec_error_errno(context, params, r, "Failed to query ambient caps: %m");
}
capability_ambient_set |= ambient_after_pam;
/* PAM modules might have set some ambient caps. Query them here and merge them into
* the caps we want to set in the end, so that we don't end up unsetting them. */
uint64_t ambient_after_pam;
r = capability_get_ambient(&ambient_after_pam);
if (r < 0) {
*exit_status = EXIT_CAPABILITIES;
return log_exec_error_errno(context, params, r, "Failed to query ambient caps: %m");
}
capability_ambient_set |= ambient_after_pam;
ngids_after_pam = getgroups_alloc(&gids_after_pam);
if (ngids_after_pam < 0) {
*exit_status = EXIT_GROUP;
@@ -5312,13 +5294,6 @@ int exec_invoke(
#endif
bset = context->capability_bounding_set;
/* If the ambient caps hack is enabled (which means the kernel can't do them, and the user asked for
* our magic fallback), then let's add some extra caps, so that the service can drop privs of its own,
* instead of us doing that */
if (needs_ambient_hack)
bset |= (UINT64_C(1) << CAP_SETPCAP) |
(UINT64_C(1) << CAP_SETUID) |
(UINT64_C(1) << CAP_SETGID);
#if HAVE_SECCOMP
/* If the service has any form of a seccomp filter and it allows dropping privileges, we'll
@@ -5361,7 +5336,7 @@ int exec_invoke(
*
* The requested ambient capabilities are raised in the inheritable set if the second
* argument is true. */
if (!needs_ambient_hack && capability_ambient_set != 0) {
if (capability_ambient_set != 0) {
r = capability_ambient_set_apply(capability_ambient_set, /* also_inherit= */ true);
if (r < 0) {
*exit_status = EXIT_CAPABILITIES;
@@ -5405,7 +5380,7 @@ int exec_invoke(
}
}
if (!needs_ambient_hack && capability_ambient_set != 0) {
if (capability_ambient_set != 0) {
/* Raise the ambient capabilities after user change. */
r = capability_ambient_set_apply(capability_ambient_set, /* also_inherit= */ false);
@@ -5591,7 +5566,7 @@ int exec_invoke(
#if HAVE_SECCOMP
/* This really should remain as close to the execve() as possible, to make sure our own code is affected
* by the filter as little as possible. */
r = apply_syscall_filter(context, params, needs_ambient_hack);
r = apply_syscall_filter(context, params);
if (r < 0) {
*exit_status = EXIT_SECCOMP;
return log_exec_error_errno(context, params, r, "Failed to apply system call filters: %m");
+16 -15
View File
@@ -933,7 +933,7 @@ int config_parse_exec(
}
const char *f = firstword;
bool ignore, separate_argv0 = false;
bool ignore, separate_argv0 = false, ambient_hack = false;
ExecCommandFlags flags = 0;
for (;; f++) {
@@ -944,28 +944,29 @@ int config_parse_exec(
* ":": Disable environment variable substitution
* "+": Run with full privileges and no sandboxing
* "!": Apply sandboxing except for user/group credentials
* "!!": Apply user/group credentials if the kernel supports ambient capabilities -
* if it doesn't we don't apply the credentials themselves, but do apply
* most other sandboxing, with some special exceptions for changing UID.
*
* The idea is that '!!' may be used to write services that can take benefit of
* systemd's UID/GID dropping if the kernel supports ambient creds, but provide
* an automatic fallback to privilege dropping within the daemon if the kernel
* does not offer that. */
*/
if (*f == '-' && !(flags & EXEC_COMMAND_IGNORE_FAILURE))
if (*f == '-' && !FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE))
flags |= EXEC_COMMAND_IGNORE_FAILURE;
else if (*f == '@' && !separate_argv0)
separate_argv0 = true;
else if (*f == ':' && !(flags & EXEC_COMMAND_NO_ENV_EXPAND))
else if (*f == ':' && !FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND))
flags |= EXEC_COMMAND_NO_ENV_EXPAND;
else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)))
else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)) && !ambient_hack)
flags |= EXEC_COMMAND_FULLY_PRIVILEGED;
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)))
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)) && !ambient_hack)
flags |= EXEC_COMMAND_NO_SETUID;
else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC))) {
else if (*f == '!' && !FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) && !ambient_hack) {
/* Compatibility with the old !! ambient caps hack (removed in v258). Since
* we don't support that anymore and !! was a noop on non-supporting systems,
* we'll just turn off the EXEC_COMMAND_NO_SETUID flag again and be done with
* it. */
flags &= ~EXEC_COMMAND_NO_SETUID;
flags |= EXEC_COMMAND_AMBIENT_MAGIC;
ambient_hack = true;
log_syntax(unit, LOG_NOTICE, filename, line, 0,
"The !! modifier for %s= lines is no longer supported and is now ignored. "
"Please update your unit files and remove the modifier.", lvalue);
} else
break;
}