chiark / gitweb /
core: rename ReadOnlySystem= to ProtectSystem= and add a third value for also mountin...
authorLennart Poettering <lennart@poettering.net>
Wed, 4 Jun 2014 16:07:55 +0000 (18:07 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 4 Jun 2014 16:12:55 +0000 (18:12 +0200)
Also, rename ProtectedHome= to ProtectHome=, to simplify things a bit.

With this in place we now have two neat options ProtectSystem= and
ProtectHome= for protecting the OS itself (and optionally its
configuration), and for protecting the user's data.

20 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/load-fragment.c
src/core/load-fragment.h
src/core/namespace.c
src/core/namespace.h
src/test/test-ns.c
units/systemd-bus-proxyd@.service.in
units/systemd-hostnamed.service.in
units/systemd-journal-gatewayd.service.in
units/systemd-journald.service.in
units/systemd-localed.service.in
units/systemd-machined.service.in
units/systemd-networkd.service.in
units/systemd-resolved.service.in
units/systemd-timedated.service.in
units/systemd-timesyncd.service.in

index 3664303..d426ac0 100644 (file)
                         </varlistentry>
 
                         <varlistentry>
-                                <term><varname>ReadOnlySystem=</varname></term>
+                                <term><varname>ProtectSystem=</varname></term>
 
                                 <listitem><para>Takes a boolean
-                                argument. If true, mounts the
-                                <filename>/usr</filename> and
-                                <filename>/boot</filename> directories
-                                read-only for processes invoked by
-                                this unit. This setting ensures that
-                                any modification of the vendor
-                                supplied operating system is
+                                argument or
+                                <literal>full</literal>. If true,
+                                mounts the <filename>/usr</filename>
+                                and <filename>/boot</filename>
+                                directories read-only for processes
+                                invoked by this unit. If set to
+                                <literal>full</literal> the
+                                <filename>/etc</filename> is mounted
+                                read-only, too. This setting ensures
+                                that any modification of the vendor
+                                supplied operating system (and
+                                optionally its configuration) is
                                 prohibited for the service. It is
                                 recommended to enable this setting for
                                 all long-running services, unless they
                         </varlistentry>
 
                         <varlistentry>
-                                <term><varname>ProtectedHome=</varname></term>
+                                <term><varname>ProtectHome=</varname></term>
 
                                 <listitem><para>Takes a boolean
                                 argument or
                                 instead. It is recommended to enable
                                 this setting for all long-running
                                 services (in particular network-facing
-                                one), to ensure they cannot get access
+                                ones), to ensure they cannot get access
                                 to private user data, unless the
                                 services actually require access to
                                 the user's private data. Note however,
index 2aa08c1..cb9a077 100644 (file)
@@ -45,7 +45,8 @@ BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutp
 
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
 
-static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protected_home, protected_home, ProtectedHome);
+static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
+static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
 
 static int property_get_environment_files(
                 sd_bus *bus,
@@ -629,8 +630,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("ProtectedHome", "s", bus_property_get_protected_home, offsetof(ExecContext, protected_home), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("ReadOnlySystem", "b", bus_property_get_bool, offsetof(ExecContext, read_only_system), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
index ce8b9bc..78fb81f 100644 (file)
@@ -1570,8 +1570,8 @@ int exec_spawn(ExecCommand *command,
                     context->mount_flags != 0 ||
                     (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) ||
                     context->private_devices ||
-                    context->read_only_system ||
-                    context->protected_home != PROTECTED_HOME_NO) {
+                    context->protect_system != PROTECT_SYSTEM_NO ||
+                    context->protect_home != PROTECT_HOME_NO) {
 
                         char *tmp = NULL, *var = NULL;
 
@@ -1595,8 +1595,8 @@ int exec_spawn(ExecCommand *command,
                                         tmp,
                                         var,
                                         context->private_devices,
-                                        context->protected_home,
-                                        context->read_only_system,
+                                        context->protect_home,
+                                        context->protect_system,
                                         context->mount_flags);
                         if (err < 0) {
                                 r = EXIT_NAMESPACE;
@@ -2114,8 +2114,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                 "%sPrivateTmp: %s\n"
                 "%sPrivateNetwork: %s\n"
                 "%sPrivateDevices: %s\n"
-                "%sProtectedHome: %s\n"
-                "%sReadOnlySystem: %s\n"
+                "%sProtectHome: %s\n"
+                "%sProtectSystem: %s\n"
                 "%sIgnoreSIGPIPE: %s\n",
                 prefix, c->umask,
                 prefix, c->working_directory ? c->working_directory : "/",
@@ -2124,8 +2124,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                 prefix, yes_no(c->private_tmp),
                 prefix, yes_no(c->private_network),
                 prefix, yes_no(c->private_devices),
-                prefix, protected_home_to_string(c->protected_home),
-                prefix, yes_no(c->read_only_system),
+                prefix, protect_home_to_string(c->protect_home),
+                prefix, protect_system_to_string(c->protect_system),
                 prefix, yes_no(c->ignore_sigpipe));
 
         STRV_FOREACH(e, c->environment)
index 3d6f77c..9d05d3a 100644 (file)
@@ -157,8 +157,8 @@ struct ExecContext {
         bool private_tmp;
         bool private_network;
         bool private_devices;
-        bool read_only_system;
-        ProtectedHome protected_home;
+        ProtectSystem protect_system;
+        ProtectHome protect_home;
 
         bool no_new_privileges;
 
index 95f59f5..089c32a 100644 (file)
@@ -80,8 +80,8 @@ $1.InaccessibleDirectories,      config_parse_namespace_path_strv,   0,
 $1.PrivateTmp,                   config_parse_bool,                  0,                             offsetof($1, exec_context.private_tmp)
 $1.PrivateNetwork,               config_parse_bool,                  0,                             offsetof($1, exec_context.private_network)
 $1.PrivateDevices,               config_parse_bool,                  0,                             offsetof($1, exec_context.private_devices)
-$1.ReadOnlySystem,               config_parse_bool,                  0,                             offsetof($1, exec_context.read_only_system)
-$1.ProtectedHome,                config_parse_protected_home,        0,                             offsetof($1, exec_context)
+$1.ProtectSystem,                config_parse_protect_system,        0,                             offsetof($1, exec_context.protect_system)
+$1.ProtectHome,                  config_parse_protect_home,          0,                             offsetof($1, exec_context.protect_home)
 $1.MountFlags,                   config_parse_exec_mount_flags,      0,                             offsetof($1, exec_context)
 $1.Personality,                  config_parse_personality,           0,                             offsetof($1, exec_context.personality)
 $1.RuntimeDirectoryMode,         config_parse_mode,                  0,                             offsetof($1, exec_context.runtime_directory_mode)
index 64d4c2f..54d3af1 100644 (file)
@@ -3101,7 +3101,7 @@ int config_parse_no_new_privileges(
         return 0;
 }
 
-int config_parse_protected_home(
+int config_parse_protect_home(
                 const char* unit,
                 const char *filename,
                 unsigned line,
@@ -3126,19 +3126,62 @@ int config_parse_protected_home(
 
         k = parse_boolean(rvalue);
         if (k > 0)
-                c->protected_home = PROTECTED_HOME_YES;
+                c->protect_home = PROTECT_HOME_YES;
         else if (k == 0)
-                c->protected_home = PROTECTED_HOME_NO;
+                c->protect_home = PROTECT_HOME_NO;
         else {
-                ProtectedHome h;
+                ProtectHome h;
 
-                h = protected_home_from_string(rvalue);
+                h = protect_home_from_string(rvalue);
                 if (h < 0){
-                        log_syntax(unit, LOG_ERR, filename, line, -h, "Failed to parse protected home value, ignoring: %s", rvalue);
+                        log_syntax(unit, LOG_ERR, filename, line, -h, "Failed to parse protect home value, ignoring: %s", rvalue);
                         return 0;
                 }
 
-                c->protected_home = h;
+                c->protect_home = h;
+        }
+
+        return 0;
+}
+
+int config_parse_protect_system(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        ExecContext *c = data;
+        int k;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        /* Our enum shall be a superset of booleans, hence first try
+         * to parse as as boolean, and then as enum */
+
+        k = parse_boolean(rvalue);
+        if (k > 0)
+                c->protect_system = PROTECT_SYSTEM_YES;
+        else if (k == 0)
+                c->protect_system = PROTECT_SYSTEM_NO;
+        else {
+                ProtectSystem s;
+
+                s = protect_system_from_string(rvalue);
+                if (s < 0){
+                        log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse protect system value, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                c->protect_system = s;
         }
 
         return 0;
index 9e4494c..1c21c46 100644 (file)
@@ -98,7 +98,8 @@ int config_parse_set_status(const char *unit, const char *filename, unsigned lin
 int config_parse_namespace_path_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_no_new_privileges(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_protected_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_protect_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 
 /* gperf prototypes */
 const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
index 1f987a4..080c086 100644 (file)
@@ -337,8 +337,8 @@ int setup_namespace(
                 char* tmp_dir,
                 char* var_tmp_dir,
                 bool private_dev,
-                ProtectedHome protected_home,
-                bool read_only_system,
+                ProtectHome protect_home,
+                ProtectSystem protect_system,
                 unsigned mount_flags) {
 
         BindMount *m, *mounts = NULL;
@@ -356,8 +356,9 @@ int setup_namespace(
                 strv_length(read_only_dirs) +
                 strv_length(inaccessible_dirs) +
                 private_dev +
-                (protected_home != PROTECTED_HOME_NO ? 2 : 0) +
-                (read_only_system ? 2 : 0);
+                (protect_home != PROTECT_HOME_NO ? 2 : 0) +
+                (protect_system != PROTECT_SYSTEM_NO ? 2 : 0) +
+                (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0);
 
         if (n > 0) {
                 m = mounts = (BindMount *) alloca(n * sizeof(BindMount));
@@ -391,14 +392,14 @@ int setup_namespace(
                         m++;
                 }
 
-                if (protected_home != PROTECTED_HOME_NO) {
-                        r = append_mounts(&m, STRV_MAKE("-/home", "-/run/user"), protected_home == PROTECTED_HOME_READ_ONLY ? READONLY : INACCESSIBLE);
+                if (protect_home != PROTECT_HOME_NO) {
+                        r = append_mounts(&m, STRV_MAKE("-/home", "-/run/user"), protect_home == PROTECT_HOME_READ_ONLY ? READONLY : INACCESSIBLE);
                         if (r < 0)
                                 return r;
                 }
 
-                if (read_only_system) {
-                        r = append_mounts(&m, STRV_MAKE("/usr", "-/boot"), READONLY);
+                if (protect_system != PROTECT_SYSTEM_NO) {
+                        r = append_mounts(&m, protect_system == PROTECT_SYSTEM_FULL ? STRV_MAKE("/usr", "/etc", "-/boot") : STRV_MAKE("/usr", "-/boot"), READONLY);
                         if (r < 0)
                                 return r;
                 }
@@ -604,10 +605,18 @@ fail:
         return r;
 }
 
-static const char *const protected_home_table[_PROTECTED_HOME_MAX] = {
-        [PROTECTED_HOME_NO] = "no",
-        [PROTECTED_HOME_YES] = "yes",
-        [PROTECTED_HOME_READ_ONLY] = "read-only",
+static const char *const protect_home_table[_PROTECT_HOME_MAX] = {
+        [PROTECT_HOME_NO] = "no",
+        [PROTECT_HOME_YES] = "yes",
+        [PROTECT_HOME_READ_ONLY] = "read-only",
 };
 
-DEFINE_STRING_TABLE_LOOKUP(protected_home, ProtectedHome);
+DEFINE_STRING_TABLE_LOOKUP(protect_home, ProtectHome);
+
+static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = {
+        [PROTECT_SYSTEM_NO] = "no",
+        [PROTECT_SYSTEM_YES] = "yes",
+        [PROTECT_SYSTEM_FULL] = "full",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(protect_system, ProtectSystem);
index b985bdf..9343fe3 100644 (file)
 
 #include "macro.h"
 
-typedef enum ProtectedHome {
-        PROTECTED_HOME_NO,
-        PROTECTED_HOME_YES,
-        PROTECTED_HOME_READ_ONLY,
-        _PROTECTED_HOME_MAX,
-        _PROTECTED_HOME_INVALID = -1
-} ProtectedHome;
+typedef enum ProtectHome {
+        PROTECT_HOME_NO,
+        PROTECT_HOME_YES,
+        PROTECT_HOME_READ_ONLY,
+        _PROTECT_HOME_MAX,
+        _PROTECT_HOME_INVALID = -1
+} ProtectHome;
+
+typedef enum ProtectSystem {
+        PROTECT_SYSTEM_NO,
+        PROTECT_SYSTEM_YES,
+        PROTECT_SYSTEM_FULL,
+        _PROTECT_SYSTEM_MAX,
+        _PROTECT_SYSTEM_INVALID = -1
+} ProtectSystem;
 
 int setup_namespace(char **read_write_dirs,
                     char **read_only_dirs,
@@ -39,8 +47,8 @@ int setup_namespace(char **read_write_dirs,
                     char *tmp_dir,
                     char *var_tmp_dir,
                     bool private_dev,
-                    ProtectedHome protected_home,
-                    bool read_only_system,
+                    ProtectHome protect_home,
+                    ProtectSystem protect_system,
                     unsigned mount_flags);
 
 int setup_tmp_dirs(const char *id,
@@ -49,5 +57,8 @@ int setup_tmp_dirs(const char *id,
 
 int setup_netns(int netns_storage_socket[2]);
 
-const char* protected_home_to_string(ProtectedHome p) _const_;
-ProtectedHome protected_home_from_string(const char *s) _pure_;
+const char* protect_home_to_string(ProtectHome p) _const_;
+ProtectHome protect_home_from_string(const char *s) _pure_;
+
+const char* protect_system_to_string(ProtectSystem p) _const_;
+ProtectSystem protect_system_from_string(const char *s) _pure_;
index 7158193..acad725 100644 (file)
@@ -60,8 +60,8 @@ int main(int argc, char *argv[]) {
                             tmp_dir,
                             var_tmp_dir,
                             true,
-                            PROTECTED_HOME_NO,
-                            false,
+                            PROTECT_HOME_NO,
+                            PROTECT_SYSTEM_NO,
                             0);
         if (r < 0) {
                 log_error("Failed to setup namespace: %s", strerror(-r));
index 3dc2cd9..0499269 100644 (file)
@@ -18,5 +18,5 @@ CapabilityBoundingSet=CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=full
+ProtectHome=yes
index 497b8d9..cc88ecd 100644 (file)
@@ -18,5 +18,5 @@ WatchdogSec=1min
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=yes
+ProtectHome=yes
index 3695240..5bd8e4b 100644 (file)
@@ -17,8 +17,8 @@ SupplementaryGroups=systemd-journal
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=full
+ProtectHome=yes
 
 [Install]
 Also=systemd-journal-gatewayd.socket
index 4a307c7..7013979 100644 (file)
@@ -21,8 +21,6 @@ RestartSec=0
 NotifyAccess=all
 StandardOutput=null
 CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID
-ReadOnlySystem=yes
-ProtectedHome=yes
 WatchdogSec=1min
 
 # Increase the default a bit in order to allow many simultaneous
index e1792d6..bfa0978 100644 (file)
@@ -18,5 +18,5 @@ WatchdogSec=1min
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=yes
+ProtectHome=yes
index 07522e1..e60ea32 100644 (file)
@@ -20,5 +20,5 @@ WatchdogSec=1min
 PrivateTmp=yes
 PrivateDevices=yes
 PrivateNetwork=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+PortectSystem=full
+ProtectHome=yes
index a928999..373ac4e 100644 (file)
@@ -20,8 +20,8 @@ Restart=always
 RestartSec=0
 ExecStart=@rootlibexecdir@/systemd-networkd
 CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=full
+ProtectHome=yes
 WatchdogSec=1min
 
 [Install]
index 787fde2..0133621 100644 (file)
@@ -16,8 +16,8 @@ Restart=always
 RestartSec=0
 ExecStart=@rootlibexecdir@/systemd-resolved
 CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=full
+ProtectHome=yes
 
 [Install]
 WantedBy=multi-user.target
index 9658149..fe5ccb4 100644 (file)
@@ -16,5 +16,5 @@ BusName=org.freedesktop.timedate1
 CapabilityBoundingSet=CAP_SYS_TIME
 WatchdogSec=1min
 PrivateTmp=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=yes
+ProtectHome=yes
index 030e4a0..8d898e2 100644 (file)
@@ -23,8 +23,8 @@ ExecStart=@rootlibexecdir@/systemd-timesyncd
 CapabilityBoundingSet=CAP_SYS_TIME CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER
 PrivateTmp=yes
 PrivateDevices=yes
-ReadOnlySystem=yes
-ProtectedHome=yes
+ProtectSystem=full
+ProtectHome=yes
 WatchdogSec=1min
 
 [Install]