summaryrefslogtreecommitdiff
path: root/src/nspawn/nspawn-settings.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-04-25 11:23:37 +0200
committerLennart Poettering <lennart@poettering.net>2019-03-15 15:41:28 +0100
commitde40a3037af944f6803375f2f5269cffc4247f56 (patch)
treea6ca09354871d5ac728aff7ee3afad0cf0571fa7 /src/nspawn/nspawn-settings.c
parent5ef4cb7ad05fdf40d6067ec7e581d21db70b0333 (diff)
downloadsystemd-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.c158
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,