diff options
author | Lennart Poettering <lennart@poettering.net> | 2017-06-28 19:22:46 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2017-06-28 13:22:46 -0400 |
commit | cd2dfc6faea2a1e2370ae52460247bb6c8c553b1 (patch) | |
tree | b2def0db525ac57c4404e6c2beffa486f2d43e00 /src/nspawn/nspawn-register.c | |
parent | 694859b5e74de0ad291453493b117c522b1e2ada (diff) | |
download | systemd-cd2dfc6faea2a1e2370ae52460247bb6c8c553b1.tar.gz |
nspawn: register a scope for the unit if --register=no is specified (#6166)
Previously, only when --register=yes was set (the default) the invoked
container would get its own scope, created by machined on behalf of
nspawn. With this change if --register=no is set nspawn will still get
its own scope (which is a good thing, so that --slice= and --property=
take effect), but this is not done through machined but by registering a
scope unit directly in PID 1.
Summary:
--register=yes → allocate a new scope through machined (the default)
--register=yes --keep-unit → use the unit we are already running in an register with machined
--register=no → allocate a new scope directly, but no machined
--register=no --keep-unit → do not allocate nor register anything
Fixes: #5823
Diffstat (limited to 'src/nspawn/nspawn-register.c')
-rw-r--r-- | src/nspawn/nspawn-register.c | 222 |
1 files changed, 165 insertions, 57 deletions
diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c index e3ab39faea..ffdf1239fa 100644 --- a/src/nspawn/nspawn-register.c +++ b/src/nspawn/nspawn-register.c @@ -27,6 +27,77 @@ #include "strv.h" #include "util.h" +static int append_machine_properties( + sd_bus_message *m, + CustomMount *mounts, + unsigned n_mounts, + int kill_signal, + char **properties) { + + unsigned j; + int r; + + assert(m); + + r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed"); + if (r < 0) + return bus_log_create_error(r); + + /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in + * sync regardless if we are run with or without the --keep-unit switch. */ + r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2, + /* Allow the container to + * access and create the API + * device nodes, so that + * PrivateDevices= in the + * container can work + * fine */ + "/dev/net/tun", "rwm", + /* Allow the container + * access to ptys. However, + * do not permit the + * container to ever create + * these device nodes. */ + "char-pts", "rw"); + if (r < 0) + return bus_log_create_error(r); + + for (j = 0; j < n_mounts; j++) { + CustomMount *cm = mounts + j; + + if (cm->type != CUSTOM_MOUNT_BIND) + continue; + + r = is_device_node(cm->source); + if (r == -ENOENT) { + /* The bind source might only appear as the image is put together, hence don't complain */ + log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source); + continue; + } + if (r < 0) + return log_error_errno(r, "Failed to stat %s: %m", cm->source); + + if (r) { + r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1, + cm->source, cm->read_only ? "r" : "rw"); + if (r < 0) + return log_error_errno(r, "Failed to append message arguments: %m"); + } + } + + if (kill_signal != 0) { + r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed"); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + int register_machine( const char *machine_name, pid_t pid, @@ -68,7 +139,6 @@ int register_machine( local_ifindex > 0 ? 1 : 0, local_ifindex); } else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - unsigned j; r = sd_bus_message_new_method_call( bus, @@ -103,63 +173,14 @@ int register_machine( return bus_log_create_error(r); } - r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed"); - if (r < 0) - return bus_log_create_error(r); - - /* If you make changes here, also make sure to update - * systemd-nspawn@.service, to keep the device - * policies in sync regardless if we are run with or - * without the --keep-unit switch. */ - r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2, - /* Allow the container to - * access and create the API - * device nodes, so that - * PrivateDevices= in the - * container can work - * fine */ - "/dev/net/tun", "rwm", - /* Allow the container - * access to ptys. However, - * do not permit the - * container to ever create - * these device nodes. */ - "char-pts", "rw"); + r = append_machine_properties( + m, + mounts, + n_mounts, + kill_signal, + properties); if (r < 0) - return bus_log_create_error(r); - - for (j = 0; j < n_mounts; j++) { - CustomMount *cm = mounts + j; - - if (cm->type != CUSTOM_MOUNT_BIND) - continue; - - r = is_device_node(cm->source); - if (r == -ENOENT) { - /* The bind source might only appear as the image is put together, hence don't complain */ - log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source); - continue; - } - if (r < 0) - return log_error_errno(r, "Failed to stat %s: %m", cm->source); - - if (r) { - r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1, - cm->source, cm->read_only ? "r" : "rw"); - if (r < 0) - return log_error_errno(r, "Failed to append message arguments: %m"); - } - } - - if (kill_signal != 0) { - r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed"); - if (r < 0) - return bus_log_create_error(r); - } + return r; r = bus_append_unit_property_assignment_many(m, properties); if (r < 0) @@ -229,3 +250,90 @@ int terminate_machine(pid_t pid) { return 0; } + +int allocate_scope( + const char *machine_name, + pid_t pid, + const char *slice, + CustomMount *mounts, + unsigned n_mounts, + int kill_signal, + char **properties) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *scope = NULL; + const char *description; + int r; + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to open system bus: %m"); + + r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope); + if (r < 0) + return log_error_errno(r, "Failed to mangle scope name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "ss", scope, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + description = strjoina("Container ", machine_name); + + r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)", + "PIDs", "au", 1, pid, + "Description", "s", description, + "Delegate", "b", 1, + "Slice", "s", isempty(slice) ? "machine.slice" : slice); + if (r < 0) + return bus_log_create_error(r); + + r = append_machine_properties( + m, + mounts, + n_mounts, + kill_signal, + properties); + if (r < 0) + return r; + + r = bus_append_unit_property_assignment_many(m, properties); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* No auxiliary units */ + r = sd_bus_message_append( + m, + "a(sa(sv))", + 0); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + log_error("Failed to allocate scope: %s", bus_error_message(&error, r)); + return r; + } + + return 0; +} |