]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #11682 from topimiettinen/private-utsname
authorLennart Poettering <lennart@poettering.net>
Wed, 20 Feb 2019 13:12:15 +0000 (14:12 +0100)
committerGitHub <noreply@github.com>
Wed, 20 Feb 2019 13:12:15 +0000 (14:12 +0100)
core: ProtectHostname feature

26 files changed:
man/systemd.exec.xml
src/core/dbus-execute.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.m4
src/core/namespace.c
src/core/namespace.h
src/shared/bus-unit-util.c
src/shared/seccomp-util.c
src/shared/seccomp-util.h
units/systemd-coredump@.service.in
units/systemd-hostnamed.service.in
units/systemd-importd.service.in
units/systemd-journal-gatewayd.service.in
units/systemd-journal-remote.service.in
units/systemd-journal-upload.service.in
units/systemd-journald.service.in
units/systemd-localed.service.in
units/systemd-logind.service.in
units/systemd-machined.service.in
units/systemd-networkd.service.in
units/systemd-portabled.service.in
units/systemd-resolved.service.in
units/systemd-timedated.service.in
units/systemd-timesyncd.service.in
units/systemd-udevd.service.in

index d39149bd0c005a8cb83202ecd9e63896dffcc29c..b8843f1ea0bb7e869de35d3db6347189f3596df1 100644 (file)
@@ -1129,6 +1129,17 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
         security.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>ProtectHostname=</varname></term>
+
+        <listitem><para>Takes a boolean argument. When set, sets up a new UTS namespace for the executed
+        processes. In addition, changing hostname or domainname is prevented. Defaults to off.</para>
+
+        <para>Note that the implementation of this setting might be impossible (for example if UTS namespaces are not
+        available), and the unit should be written in a way that does not solely rely on this setting for
+        security.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>ProtectKernelTunables=</varname></term>
 
index 11301e4b693679d91f73ed1d6c964030a2b65c12..f22bf4a371c54eb1c8125bfa9c4a8f00823c930a 100644 (file)
@@ -777,6 +777,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
 
         /* Obsolete/redundant properties: */
         SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
@@ -1153,6 +1154,9 @@ int bus_exec_context_set_transient_property(
         if (streq(name, "LockPersonality"))
                 return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error);
 
+        if (streq(name, "ProtectHostname"))
+                return bus_set_transient_bool(u, name, &c->protect_hostname, message, flags, error);
+
         if (streq(name, "UtmpIdentifier"))
                 return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error);
 
index 0695527968a13d0f286fe8d9023abf8db04697df..42a09333b158a5b8dff1bd3c9a4626cee76e923d 100644 (file)
@@ -1410,7 +1410,8 @@ static bool context_has_no_new_privileges(const ExecContext *c) {
                 c->private_devices ||
                 context_has_syscall_filters(c) ||
                 !set_isempty(c->syscall_archs) ||
-                c->lock_personality;
+                c->lock_personality ||
+                c->protect_hostname;
 }
 
 #if HAVE_SECCOMP
@@ -2420,6 +2421,7 @@ static int apply_mount_namespace(
                         .protect_control_groups = context->protect_control_groups,
                         .protect_kernel_tunables = context->protect_kernel_tunables,
                         .protect_kernel_modules = context->protect_kernel_modules,
+                        .protect_hostname = context->protect_hostname,
                         .mount_apivfs = context->mount_apivfs,
                         .private_mounts = context->private_mounts,
                 };
@@ -3289,6 +3291,23 @@ static int exec_child(
                 }
         }
 
+        if (context->protect_hostname) {
+                if (ns_type_supported(NAMESPACE_UTS)) {
+                        if (unshare(CLONE_NEWUTS) < 0) {
+                                *exit_status = EXIT_NAMESPACE;
+                                return log_unit_error_errno(unit, errno, "Failed to set up UTS namespacing: %m");
+                        }
+                } else
+                        log_unit_warning(unit, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup.");
+#if HAVE_SECCOMP
+                r = seccomp_protect_hostname();
+                if (r < 0) {
+                        *exit_status = EXIT_SECCOMP;
+                        return log_unit_error_errno(unit, r, "Failed to apply hostname restrictions: %m");
+                }
+#endif
+        }
+
         /* Drop groups as early as possbile */
         if (needs_setuid) {
                 r = enforce_groups(gid, supplementary_gids, ngids);
@@ -4166,7 +4185,8 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
                 "%sIgnoreSIGPIPE: %s\n"
                 "%sMemoryDenyWriteExecute: %s\n"
                 "%sRestrictRealtime: %s\n"
-                "%sKeyringMode: %s\n",
+                "%sKeyringMode: %s\n"
+                "%sProtectHostname: %s\n",
                 prefix, c->umask,
                 prefix, c->working_directory ? c->working_directory : "/",
                 prefix, c->root_directory ? c->root_directory : "/",
@@ -4184,7 +4204,8 @@ 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, exec_keyring_mode_to_string(c->keyring_mode));
+                prefix, exec_keyring_mode_to_string(c->keyring_mode),
+                prefix, yes_no(c->protect_hostname));
 
         if (c->root_image)
                 fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
index 0f1bf56744bb5d5d4d3defda249cfc279a49d9a0..12a6e92b6598bdce347cb51d3ce4df7c9c9041a1 100644 (file)
@@ -272,6 +272,7 @@ struct ExecContext {
 
         bool memory_deny_write_execute;
         bool restrict_realtime;
+        bool protect_hostname;
 
         bool oom_score_adjust_set:1;
         bool nice_set:1;
index ca3923bbb0842bf81d0bddffed32be50493b33be..2ac822ef4b2a6d9e3d17b3fffb91d22dbe741ff7 100644 (file)
@@ -133,6 +133,7 @@ $1.LogsDirectoryMode,            config_parse_mode,                  0,
 $1.LogsDirectory,                config_parse_exec_directories,      0,                             offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].paths)
 $1.ConfigurationDirectoryMode,   config_parse_mode,                  0,                             offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode)
 $1.ConfigurationDirectory,       config_parse_exec_directories,      0,                             offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].paths)
+$1.ProtectHostname,              config_parse_bool,                  0,                             offsetof($1, exec_context.protect_hostname)
 m4_ifdef(`HAVE_PAM',
 `$1.PAMName,                     config_parse_unit_string_printf,    0,                             offsetof($1, exec_context.pam_name)',
 `$1.PAMName,                     config_parse_warn_compat,           DISABLED_CONFIGURATION,        0')
index 7f553a42c2b5145236692b05637459b360e59bd9..d482c40c240a523f35f8c254dda419940a783f0a 100644 (file)
@@ -1117,6 +1117,7 @@ static size_t namespace_calculate_mounts(
                 (ns_info->protect_control_groups ? 1 : 0) +
                 (ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) +
                 protect_home_cnt + protect_system_cnt +
+                (ns_info->protect_hostname ? 2 : 0) +
                 (namespace_info_mount_apivfs(ns_info) ? ELEMENTSOF(apivfs_table) : 0);
 }
 
@@ -1301,6 +1302,17 @@ int setup_namespace(
                                 goto finish;
                 }
 
+                if (ns_info->protect_hostname) {
+                        *(m++) = (MountEntry) {
+                                .path_const = "/proc/sys/kernel/hostname",
+                                .mode = READONLY,
+                        };
+                        *(m++) = (MountEntry) {
+                                .path_const = "/proc/sys/kernel/domainname",
+                                .mode = READONLY,
+                        };
+                }
+
                 assert(mounts + n_mounts == m);
 
                 /* Prepend the root directory where that's necessary */
index 5e0ec97969d0d1c700f6b924e6b485415d8bf847..ab3983f790c2213674f8c3a8f9ad86ecce595e42 100644 (file)
@@ -52,6 +52,7 @@ struct NamespaceInfo {
         bool protect_kernel_tunables:1;
         bool protect_kernel_modules:1;
         bool mount_apivfs:1;
+        bool protect_hostname:1;
 };
 
 struct BindMount {
index a74b213155b568a5ea69c481bfd74d76219fcde9..dff87f565ed991772fea9f8bab86662623995bd5 100644 (file)
@@ -754,7 +754,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
                        "PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix",
                        "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC",
                        "ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups",
-                       "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality"))
+                       "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality", "ProtectHostname"))
 
                 return bus_append_parse_boolean(m, field, eq);
 
index cc58b3c07879d4bb0d7fd143e239c4bbd49bd96e..98a0066baec60b335754acaa2a2661e5779695a0 100644 (file)
@@ -1762,3 +1762,40 @@ int seccomp_lock_personality(unsigned long personality) {
 
         return 0;
 }
+
+int seccomp_protect_hostname(void) {
+        uint32_t arch;
+        int r;
+
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
+
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
+                if (r < 0)
+                        return r;
+
+                r = seccomp_rule_add_exact(
+                                seccomp,
+                                SCMP_ACT_ERRNO(EPERM),
+                                SCMP_SYS(sethostname),
+                                0);
+                if (r < 0)
+                        continue;
+
+                r = seccomp_rule_add_exact(
+                                seccomp,
+                                SCMP_ACT_ERRNO(EPERM),
+                                SCMP_SYS(setdomainname),
+                                0);
+                if (r < 0)
+                        continue;
+
+                r = seccomp_load(seccomp);
+                if (IN_SET(r, -EPERM, -EACCES))
+                        return r;
+                if (r < 0)
+                        log_debug_errno(r, "Failed to apply hostname restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+        }
+
+        return 0;
+}
index d8a36c4e21c2f411f290753d156f30775d06d35a..477400237b3b087f3849d70e32de4d3d69ab4759 100644 (file)
@@ -85,6 +85,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist);
 int seccomp_restrict_realtime(void);
 int seccomp_memory_deny_write_execute(void);
 int seccomp_lock_personality(unsigned long personality);
+int seccomp_protect_hostname(void);
 
 extern const uint32_t seccomp_local_archs[];
 
index ffcb5f36ca6c551ab74c7c7a79161d8dc97fafa4..f6166fa11ce839e3bec8ff7fa61579182acfd67b 100644 (file)
@@ -29,6 +29,7 @@ PrivateNetwork=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 9c925e80d9fe57bb1acb0bc3c0d2d4a4e0e6ab33..62e9b28f5b702d00d7c2cfc74e8c8b2189042ace 100644 (file)
@@ -25,6 +25,7 @@ PrivateNetwork=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 20704a82324780d9f41ad9af8b1574caf901a7a5..38b7d7e94b4745f45e94f666fa101d8e3c76b9f9 100644 (file)
@@ -20,6 +20,7 @@ KillMode=mixed
 CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE
 NoNewPrivileges=yes
 MemoryDenyWriteExecute=yes
+ProtectHostname=yes
 RestrictRealtime=yes
 RestrictNamespaces=net
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
index ebc8bf9a254368b981d7e43391e0c7223657ed2d..0f16ae4ccba1927cb85cb95b0acf7595d5b82d0c 100644 (file)
@@ -22,6 +22,7 @@ PrivateDevices=yes
 PrivateNetwork=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
index 29a99aaec1ae0281d6a0dc4499db93528c26fa25..71727295c3d576bfd6043c97129de3aeacf04dd9 100644 (file)
@@ -23,6 +23,7 @@ PrivateNetwork=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 92cd4e52592bf1ff4b87fa11b86ba7577fc963e7..10e4d657d3ac319f4c9c0b716f5bfce403dd4281 100644 (file)
@@ -22,6 +22,7 @@ NoNewPrivileges=yes
 PrivateDevices=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
index 4684f095c0778f4d21d376bab2c6c1e36dba9bab..1807d73c68586297776b2053816670ce56f79e45 100644 (file)
@@ -23,6 +23,7 @@ IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
+ProtectHostname=yes
 Restart=always
 RestartSec=0
 RestrictAddressFamilies=AF_UNIX AF_NETLINK
index 01e0703d0e207c7da718feb6dd26f2d21becca24..a64e7e79a8fbbebcca7a7ff5f22c19bcd575af5d 100644 (file)
@@ -25,6 +25,7 @@ PrivateNetwork=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 38a7f269aca173af5f5c66ceaaaea009a2b2d766..fb6fda49077742d746fb106c194bc88da884a59c 100644 (file)
@@ -28,6 +28,7 @@ IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
+ProtectHostname=yes
 Restart=always
 RestartSec=0
 RestrictAddressFamilies=AF_UNIX AF_NETLINK
index 9f1476814df60d96d47f48b1144b75a38f7b201b..d6deefea083a508ac458623a5443e00fefa4356d 100644 (file)
@@ -23,6 +23,7 @@ IPAddressDeny=any
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
+ProtectHostname=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 RestrictRealtime=yes
 SystemCallArchitectures=native
index 472ef045de9e5cce5f421ef27a2ff4643a0be22b..5da0e1e3307e720e6558d22b6b95fe322a702cce 100644 (file)
@@ -27,6 +27,7 @@ MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectSystem=strict
 Restart=on-failure
index a44cdb30a42f673b7327d2d82fd19f47d16ef049..a8eab94d02e524738f58210bf200afee034e6033 100644 (file)
@@ -18,6 +18,7 @@ BusName=org.freedesktop.portable1
 WatchdogSec=3min
 CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD
 MemoryDenyWriteExecute=yes
+ProtectHostname=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 SystemCallFilter=@system-service @mount
index 3144b70063ee3acc4bd4a1fb704e7824143b1d23..eac3f31012ca8f59b1dfc41f26aaf0bd495f4fb4 100644 (file)
@@ -30,6 +30,7 @@ PrivateDevices=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 6d5302419579bf5c4e52adf2ffb4c1f2be3898fe..46ee8c894df6ae65251155b47977beab38008454 100644 (file)
@@ -23,6 +23,7 @@ NoNewPrivileges=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 03ade45d0868e57e74614320b3e1e34df13adf23..5313a90c30b62390b04f4a5c6bdf5eb53ffbe571 100644 (file)
@@ -29,6 +29,7 @@ PrivateDevices=yes
 PrivateTmp=yes
 ProtectControlGroups=yes
 ProtectHome=yes
+ProtectHostname=yes
 ProtectKernelModules=yes
 ProtectKernelTunables=yes
 ProtectSystem=strict
index 6a3814e5d92607a397b88bb55015a6be47bc75ff..fb98ca4d43a2094484e2adafb7cca638fa85ec7c 100644 (file)
@@ -26,6 +26,7 @@ KillMode=mixed
 WatchdogSec=3min
 TasksMax=infinity
 PrivateMounts=yes
+ProtectHostname=yes
 MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6