diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index d894dbdd7b8..653847acad4 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -771,6 +771,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), @@ -1128,6 +1129,9 @@ int bus_exec_context_set_transient_property( if (streq(name, "RestrictRealtime")) return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error); + if (streq(name, "RestrictSUIDSGID")) + return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error); + if (streq(name, "DynamicUser")) return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error); diff --git a/src/core/execute.c b/src/core/execute.c index a74967c4d3d..5e1a74d0bce 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1404,6 +1404,7 @@ static bool context_has_no_new_privileges(const ExecContext *c) { return context_has_address_families(c) || c->memory_deny_write_execute || c->restrict_realtime || + c->restrict_suid_sgid || exec_context_restrict_namespaces_set(c) || c->protect_kernel_tunables || c->protect_kernel_modules || @@ -1509,6 +1510,19 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { return seccomp_restrict_realtime(); } +static int apply_restrict_suid_sgid(const Unit* u, const ExecContext *c) { + assert(u); + assert(c); + + if (!c->restrict_suid_sgid) + return 0; + + if (skip_seccomp_unavailable(u, "RestrictSUIDSGID=")) + return 0; + + return seccomp_restrict_suid_sgid(); +} + static int apply_protect_sysctl(const Unit *u, const ExecContext *c) { assert(u); assert(c); @@ -3567,6 +3581,12 @@ static int exec_child( return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m"); } + r = apply_restrict_suid_sgid(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply SUID/SGID restrictions: %m"); + } + r = apply_restrict_namespaces(unit, context); if (r < 0) { *exit_status = EXIT_SECCOMP; @@ -4218,6 +4238,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { "%sIgnoreSIGPIPE: %s\n" "%sMemoryDenyWriteExecute: %s\n" "%sRestrictRealtime: %s\n" + "%sRestrictSUIDSGID: %s\n" "%sKeyringMode: %s\n" "%sProtectHostname: %s\n", prefix, c->umask, @@ -4237,6 +4258,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->ignore_sigpipe), prefix, yes_no(c->memory_deny_write_execute), prefix, yes_no(c->restrict_realtime), + prefix, yes_no(c->restrict_suid_sgid), prefix, exec_keyring_mode_to_string(c->keyring_mode), prefix, yes_no(c->protect_hostname)); diff --git a/src/core/execute.h b/src/core/execute.h index b612a10e2e6..23bf3b546ad 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -261,6 +261,7 @@ struct ExecContext { bool memory_deny_write_execute; bool restrict_realtime; + bool restrict_suid_sgid; bool lock_personality; unsigned long personality; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index a2ed7f2abe3..73b368e702a 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -74,6 +74,7 @@ $1.SystemCallErrorNumber, config_parse_syscall_errno, 0, $1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute) $1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context) $1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime) +$1.RestrictSUIDSGID, config_parse_bool, 0, offsetof($1, exec_context.restrict_suid_sgid) $1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context) $1.LockPersonality, config_parse_bool, 0, offsetof($1, exec_context.lock_personality)', `$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 @@ -82,6 +83,7 @@ $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CO $1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION 0 $1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 $1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') $1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit) diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index b27227aeb6c..b42a9e5c5b6 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -746,12 +746,12 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con return bus_append_string(m, field, eq); if (STR_IN_SET(field, - "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", - "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", - "PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix", - "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC", - "ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups", - "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality", "ProtectHostname")) + "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", "PrivateTmp", + "PrivateDevices", "PrivateNetwork", "PrivateUsers", "PrivateMounts", + "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", "RestrictRealtime", + "DynamicUser", "RemoveIPC", "ProtectKernelTunables", "ProtectKernelModules", + "ProtectControlGroups", "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality", + "ProtectHostname", "RestrictSUIDSGID")) return bus_append_parse_boolean(m, field, eq); diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 2fdfd51d60d..86e59184d74 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -851,6 +851,7 @@ ReserveVT= RestrictAddressFamilies= RestrictNamespaces= RestrictRealtime= +RestrictSUIDSGID= RuntimeDirectory= RuntimeDirectoryMode= RuntimeDirectoryPreserve=