summaryrefslogtreecommitdiff
path: root/src/nspawn/nspawn-register.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-06-28 19:22:46 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-06-28 13:22:46 -0400
commitcd2dfc6faea2a1e2370ae52460247bb6c8c553b1 (patch)
treeb2def0db525ac57c4404e6c2beffa486f2d43e00 /src/nspawn/nspawn-register.c
parent694859b5e74de0ad291453493b117c522b1e2ada (diff)
downloadsystemd-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.c222
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;
+}