diff options
author | Lennart Poettering <lennart@poettering.net> | 2018-04-25 11:23:37 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-03-15 15:41:28 +0100 |
commit | de40a3037af944f6803375f2f5269cffc4247f56 (patch) | |
tree | a6ca09354871d5ac728aff7ee3afad0cf0571fa7 /src/nspawn/nspawn-settings.c | |
parent | 5ef4cb7ad05fdf40d6067ec7e581d21db70b0333 (diff) | |
download | systemd-de40a3037af944f6803375f2f5269cffc4247f56.tar.gz |
nspawn: add support for executing OCI runtime bundles with nspawn
This is a pretty large patch, and adds support for OCI runtime bundles
to nspawn. A new switch --oci-bundle= is added that takes a path to an
OCI bundle. The JSON file included therein is read similar to a .nspawn
settings files, however with a different feature set.
Implementation-wise this mostly extends the pre-existing Settings object
to carry additional properties for OCI. However, OCI supports some
concepts .nspawn files did not support yet, which this patch also adds:
1. Support for "masking" files and directories. This functionatly is now
also available via the new --inaccesible= cmdline command, and
Inaccessible= in .nspawn files.
2. Support for mounting arbitrary file systems. (not exposed through
nspawn cmdline nor .nspawn files, because probably not a good idea)
3. Ability to configure the console settings for a container. This
functionality is now also available on the nspawn cmdline in the new
--console= switch (not added to .nspawn for now, as it is something
specific to the invocation really, not a property of the container)
4. Console width/height configuration. Not exposed through
.nspawn/cmdline, but this may be controlled through $COLUMNS and
$LINES like in most other UNIX tools.
5. UID/GID configuration by raw numbers. (not exposed in .nspawn and on
the cmdline, since containers likely have different user tables, and
the existing --user= switch appears to be the better option)
6. OCI hook commands (no exposed in .nspawn/cmdline, as very specific to
OCI)
7. Creation of additional devices nodes in /dev. Most likely not a good
idea, hence not exposed in .nspawn/cmdline. There's already --bind=
to achieve the same, which is the better alternative.
8. Explicit syscall filters. This is not a good idea, due to the skewed
arch support, hence not exposed through .nspawn/cmdline.
9. Configuration of some sysctls on a whitelist. Questionnable, not
supported in .nspawn/cmdline for now.
10. Configuration of all 5 types of capabilities. Not a useful concept,
since the kernel will reduce the caps on execve() anyway. Not
exposed through .nspawn/cmdline as this is not very useful hence.
Note that this only implements the OCI runtime logic itself. It does not
provide a runc-compatible command line tool. This is left for a later
PR. Only with that in place tools such as "buildah" can use the OCI
support in nspawn as drop-in replacement.
Currently still missing is OCI hook support, but it's already parsed and
everything, and should be easy to add. Other than that it's OCI is
implemented pretty comprehensively.
There's a list of incompatibilities in the nspawn-oci.c file. In a later
PR I'd like to convert this into proper markdown and add it to the
documentation directory.
Diffstat (limited to 'src/nspawn/nspawn-settings.c')
-rw-r--r-- | src/nspawn/nspawn-settings.c | 158 |
1 files changed, 138 insertions, 20 deletions
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c index 505e8cac40..ab69f24c54 100644 --- a/src/nspawn/nspawn-settings.c +++ b/src/nspawn/nspawn-settings.c @@ -17,6 +17,50 @@ #include "user-util.h" #include "util.h" +Settings *settings_new(void) { + Settings *s; + + s = new(Settings, 1); + if (!s) + return NULL; + + *s = (Settings) { + .start_mode = _START_MODE_INVALID, + .personality = PERSONALITY_INVALID, + + .resolv_conf = _RESOLV_CONF_MODE_INVALID, + .link_journal = _LINK_JOURNAL_INVALID, + .timezone = _TIMEZONE_MODE_INVALID, + + .userns_mode = _USER_NAMESPACE_MODE_INVALID, + .userns_chown = -1, + .uid_shift = UID_INVALID, + .uid_range = UID_INVALID, + + .no_new_privileges = -1, + + .read_only = -1, + .volatile_mode = _VOLATILE_MODE_INVALID, + + .private_network = -1, + .network_veth = -1, + + .full_capabilities = CAPABILITY_QUINTET_NULL, + + .uid = UID_INVALID, + .gid = GID_INVALID, + + .console_mode = _CONSOLE_MODE_INVALID, + .console_width = (unsigned) -1, + .console_height = (unsigned) -1, + + .clone_ns_flags = (unsigned long) -1, + .use_cgns = -1, + }; + + return s; +} + int settings_load(FILE *f, const char *path, Settings **ret) { _cleanup_(settings_freep) Settings *s = NULL; int r; @@ -24,27 +68,10 @@ int settings_load(FILE *f, const char *path, Settings **ret) { assert(path); assert(ret); - s = new0(Settings, 1); + s = settings_new(); if (!s) return -ENOMEM; - s->start_mode = _START_MODE_INVALID; - s->personality = PERSONALITY_INVALID; - s->userns_mode = _USER_NAMESPACE_MODE_INVALID; - s->resolv_conf = _RESOLV_CONF_MODE_INVALID; - s->link_journal = _LINK_JOURNAL_INVALID; - s->timezone = _TIMEZONE_MODE_INVALID; - s->uid_shift = UID_INVALID; - s->uid_range = UID_INVALID; - s->no_new_privileges = -1; - - s->read_only = -1; - s->volatile_mode = _VOLATILE_MODE_INVALID; - s->userns_chown = -1; - - s->private_network = -1; - s->network_veth = -1; - r = config_parse(NULL, path, f, "Exec\0" "Network\0" @@ -66,12 +93,33 @@ int settings_load(FILE *f, const char *path, Settings **ret) { s->userns_mode = USER_NAMESPACE_NO; *ret = TAKE_PTR(s); - return 0; } -Settings* settings_free(Settings *s) { +static void free_oci_hooks(OciHook *h, size_t n) { + size_t i; + + assert(h || n == 0); + + for (i = 0; i < n; i++) { + free(h[i].path); + strv_free(h[i].args); + strv_free(h[i].env); + } + + free(h); +} + +void device_node_free_many(DeviceNode *node, size_t n) { + size_t i; + + for (i = 0; i < n; i++) + free(node[i].path); + + free(node); +} +Settings* settings_free(Settings *s) { if (!s) return NULL; @@ -96,6 +144,28 @@ Settings* settings_free(Settings *s) { expose_port_free_all(s->expose_ports); custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); + + free(s->bundle); + free(s->root); + + free_oci_hooks(s->oci_hooks_prestart, s->n_oci_hooks_prestart); + free_oci_hooks(s->oci_hooks_poststart, s->n_oci_hooks_poststart); + free_oci_hooks(s->oci_hooks_poststop, s->n_oci_hooks_poststop); + + free(s->slice); + sd_bus_message_unref(s->properties); + + free(s->supplementary_gids); + device_node_free_many(s->extra_nodes, s->n_extra_nodes); + free(s->extra_nodes); + free(s->network_namespace_path); + + strv_free(s->sysctl); + +#if HAVE_SECCOMP + seccomp_release(s->seccomp); +#endif + return mfree(s); } @@ -122,6 +192,26 @@ bool settings_network_veth(Settings *s) { s->network_zone; } +int settings_allocate_properties(Settings *s) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + int r; + + assert(s); + + if (s->properties) + return 0; + + r = sd_bus_default_system(&bus); + if (r < 0) + return r; + + r = sd_bus_message_new(bus, &s->properties, SD_BUS_MESSAGE_METHOD_CALL); + if (r < 0) + return r; + + return 0; +} + DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode"); int config_parse_expose_port( @@ -315,6 +405,34 @@ int config_parse_tmpfs( return 0; } +int config_parse_inaccessible( + 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 = inaccessible_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid inaccessible file system specification %s: %m", rvalue); + return 0; + } + + return 0; +} + int config_parse_overlay( const char *unit, const char *filename, |