From 1b8689f94983b47bf190e77ddb03a8fc6af15fb3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Jun 2014 18:07:55 +0200 Subject: core: rename ReadOnlySystem= to ProtectSystem= and add a third value for also mounting /etc read-only 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. --- src/core/dbus-execute.c | 7 +++-- src/core/execute.c | 16 +++++----- src/core/execute.h | 4 +-- src/core/load-fragment-gperf.gperf.m4 | 4 +-- src/core/load-fragment.c | 57 ++++++++++++++++++++++++++++++----- src/core/load-fragment.h | 3 +- src/core/namespace.c | 35 +++++++++++++-------- src/core/namespace.h | 33 +++++++++++++------- src/test/test-ns.c | 4 +-- 9 files changed, 114 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 2aa08c1435..cb9a077d0e 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -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), diff --git a/src/core/execute.c b/src/core/execute.c index ce8b9bcb8b..78fb81f726 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -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) diff --git a/src/core/execute.h b/src/core/execute.h index 3d6f77c8ef..9d05d3a9de 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -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; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 95f59f55d9..089c32a81e 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -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) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 64d4c2f639..54d3af1a99 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -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; diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 9e4494cf98..1c21c466d2 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -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); diff --git a/src/core/namespace.c b/src/core/namespace.c index 1f987a4b9d..080c086fd4 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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); diff --git a/src/core/namespace.h b/src/core/namespace.h index b985bdf512..9343fe3264 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -25,13 +25,21 @@ #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_; diff --git a/src/test/test-ns.c b/src/test/test-ns.c index 71581934cb..acad725899 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -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)); -- cgit v1.2.3-54-g00ecf