diff options
Diffstat (limited to 'src/systemd-nspawn/nspawn-settings.c')
-rw-r--r-- | src/systemd-nspawn/nspawn-settings.c | 124 |
1 files changed, 123 insertions, 1 deletions
diff --git a/src/systemd-nspawn/nspawn-settings.c b/src/systemd-nspawn/nspawn-settings.c index 4fb0054698..5f1522cfb6 100644 --- a/src/systemd-nspawn/nspawn-settings.c +++ b/src/systemd-nspawn/nspawn-settings.c @@ -24,7 +24,10 @@ #include "nspawn-settings.h" #include "parse-util.h" #include "process-util.h" +#include "socket-util.h" +#include "string-util.h" #include "strv.h" +#include "user-util.h" #include "util.h" int settings_load(FILE *f, const char *path, Settings **ret) { @@ -40,9 +43,13 @@ int settings_load(FILE *f, const char *path, Settings **ret) { s->start_mode = _START_MODE_INVALID; s->personality = PERSONALITY_INVALID; + s->userns_mode = _USER_NAMESPACE_MODE_INVALID; + s->uid_shift = UID_INVALID; + s->uid_range = UID_INVALID; s->read_only = -1; s->volatile_mode = _VOLATILE_MODE_INVALID; + s->userns_chown = -1; s->private_network = -1; s->network_veth = -1; @@ -59,6 +66,16 @@ int settings_load(FILE *f, const char *path, Settings **ret) { if (r < 0) return r; + /* Make sure that if userns_mode is set, userns_chown is set to something appropriate, and vice versa. Either + * both fields shall be initialized or neither. */ + if (s->userns_mode == USER_NAMESPACE_PICK) + s->userns_chown = true; + else if (s->userns_mode != _USER_NAMESPACE_MODE_INVALID && s->userns_chown < 0) + s->userns_chown = false; + + if (s->userns_chown >= 0 && s->userns_mode == _USER_NAMESPACE_MODE_INVALID) + s->userns_mode = USER_NAMESPACE_NO; + *ret = s; s = NULL; @@ -80,6 +97,7 @@ Settings* settings_free(Settings *s) { strv_free(s->network_ipvlan); strv_free(s->network_veth_extra); free(s->network_bridge); + free(s->network_zone); expose_port_free_all(s->expose_ports); custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); @@ -95,6 +113,7 @@ bool settings_private_network(Settings *s) { s->private_network > 0 || s->network_veth > 0 || s->network_bridge || + s->network_zone || s->network_interfaces || s->network_macvlan || s->network_ipvlan || @@ -106,7 +125,8 @@ bool settings_network_veth(Settings *s) { return s->network_veth > 0 || - s->network_bridge; + s->network_bridge || + s->network_zone; } DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode"); @@ -303,6 +323,38 @@ int config_parse_veth_extra( return 0; } +int config_parse_network_zone( + 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) { + + Settings *settings = data; + _cleanup_free_ char *j = NULL; + + assert(filename); + assert(lvalue); + assert(rvalue); + + j = strappend("vz-", rvalue); + if (!ifname_valid(j)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid network zone name %s, ignoring: %m", rvalue); + return 0; + } + + free(settings->network_zone); + settings->network_zone = j; + j = NULL; + + return 0; +} + int config_parse_boot( const char *unit, const char *filename, @@ -392,3 +444,73 @@ conflict: log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); return 0; } + +int config_parse_private_users( + 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) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = parse_boolean(rvalue); + if (r == 0) { + /* no: User namespacing off */ + settings->userns_mode = USER_NAMESPACE_NO; + settings->uid_shift = UID_INVALID; + settings->uid_range = UINT32_C(0x10000); + } else if (r > 0) { + /* yes: User namespacing on, UID range is read from root dir */ + settings->userns_mode = USER_NAMESPACE_FIXED; + settings->uid_shift = UID_INVALID; + settings->uid_range = UINT32_C(0x10000); + } else if (streq(rvalue, "pick")) { + /* pick: User namespacing on, UID range is picked randomly */ + settings->userns_mode = USER_NAMESPACE_PICK; + settings->uid_shift = UID_INVALID; + settings->uid_range = UINT32_C(0x10000); + } else { + const char *range, *shift; + uid_t sh, rn; + + /* anything else: User namespacing on, UID range is explicitly configured */ + + range = strchr(rvalue, ':'); + if (range) { + shift = strndupa(rvalue, range - rvalue); + range++; + + r = safe_atou32(range, &rn); + if (r < 0 || rn <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID range invalid, ignoring: %s", range); + return 0; + } + } else { + shift = rvalue; + rn = UINT32_C(0x10000); + } + + r = parse_uid(shift, &sh); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID shift invalid, ignoring: %s", range); + return 0; + } + + settings->userns_mode = USER_NAMESPACE_FIXED; + settings->uid_shift = sh; + settings->uid_range = rn; + } + + return 0; +} |