summaryrefslogtreecommitdiff
path: root/src/nspawn
diff options
context:
space:
mode:
Diffstat (limited to 'src/nspawn')
-rw-r--r--src/nspawn/nspawn-cgroup.c2
-rw-r--r--src/nspawn/nspawn-mount.c25
-rw-r--r--src/nspawn/nspawn-register.c11
-rw-r--r--src/nspawn/nspawn-seccomp.c6
-rw-r--r--src/nspawn/nspawn-setuid.c7
-rw-r--r--src/nspawn/nspawn.c88
6 files changed, 61 insertions, 78 deletions
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index f50f1ad6c2..b1580236c9 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -123,7 +123,7 @@ int create_subcgroup(pid_t pid, bool unified_requested) {
int unified, r;
CGroupMask supported;
- /* In the unified hierarchy inner nodes may only only contain
+ /* In the unified hierarchy inner nodes may only contain
* subgroups, but not processes. Hence, if we running in the
* unified hierarchy and the container does the same, and we
* did not create a scope unit for the container move us and
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index b76b09b9cb..ac93357ef4 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -315,18 +315,19 @@ int mount_all(const char *dest,
} MountPoint;
static const MountPoint mount_table[] = {
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true, false },
- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true, false }, /* Bind mount first */
- { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true, false }, /* Then, make it r/o */
- { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, true },
- { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, false },
- { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false, false },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false },
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false, false },
+ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true, false },
+ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true, false }, /* Bind mount first ...*/
+ { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, true, true, true }, /* (except for this) */
+ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true, false }, /* ... then, make it r/o */
+ { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, true },
+ { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, false },
+ { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false, false },
+ { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false },
+ { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false },
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false, false },
#ifdef HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false, false }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false }, /* Then, make it r/o */
+ { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false, false }, /* Bind mount first */
+ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false }, /* Then, make it r/o */
#endif
};
@@ -360,7 +361,7 @@ int mount_all(const char *dest,
if (mount_table[k].fatal)
return log_error_errno(r, "Failed to create directory %s: %m", where);
- log_warning_errno(r, "Failed to create directory %s: %m", where);
+ log_debug_errno(r, "Failed to create directory %s: %m", where);
continue;
}
diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c
index 20103c5e88..e5b76a0c5d 100644
--- a/src/nspawn/nspawn-register.c
+++ b/src/nspawn/nspawn-register.c
@@ -104,7 +104,7 @@ int register_machine(
return bus_log_create_error(r);
}
- r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
+ r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
if (r < 0)
return bus_log_create_error(r);
@@ -112,26 +112,19 @@ int register_machine(
* 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)", 9,
+ 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/null", "rwm",
- "/dev/zero", "rwm",
- "/dev/full", "rwm",
- "/dev/random", "rwm",
- "/dev/urandom", "rwm",
- "/dev/tty", "rwm",
"/dev/net/tun", "rwm",
/* Allow the container
* access to ptys. However,
* do not permit the
* container to ever create
* these device nodes. */
- "/dev/pts/ptmx", "rw",
"char-pts", "rw");
if (r < 0)
return bus_log_create_error(r);
diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c
index 54db1b47f8..3ab7160ebe 100644
--- a/src/nspawn/nspawn-seccomp.c
+++ b/src/nspawn/nspawn-seccomp.c
@@ -119,10 +119,8 @@ static int seccomp_add_default_syscall_filter(scmp_filter_ctx ctx,
r = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0);
if (r == -EFAULT)
continue; /* unknown syscall */
- if (r < 0) {
- log_error_errno(r, "Failed to block syscall: %m");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to block syscall: %m");
}
return 0;
diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c
index ee15a47e93..b8e8e091c8 100644
--- a/src/nspawn/nspawn-setuid.c
+++ b/src/nspawn/nspawn-setuid.c
@@ -124,14 +124,12 @@ int change_uid_gid(const char *user, char **_home) {
fd = -1;
if (!fgets(line, sizeof(line), f)) {
-
if (!ferror(f)) {
log_error("Failed to resolve user %s.", user);
return -ESRCH;
}
- log_error_errno(errno, "Failed to read from getent: %m");
- return -errno;
+ return log_error_errno(errno, "Failed to read from getent: %m");
}
truncate_nl(line);
@@ -214,8 +212,7 @@ int change_uid_gid(const char *user, char **_home) {
return -ESRCH;
}
- log_error_errno(errno, "Failed to read from getent: %m");
- return -errno;
+ return log_error_errno(errno, "Failed to read from getent: %m");
}
truncate_nl(line);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 9e74a77758..d5093a6d17 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -61,9 +61,9 @@
#include "fs-util.h"
#include "gpt.h"
#include "hostname-util.h"
+#include "id128-util.h"
#include "log.h"
#include "loopback-setup.h"
-#include "machine-id-setup.h"
#include "machine-image.h"
#include "macro.h"
#include "missing.h"
@@ -76,10 +76,10 @@
#include "nspawn-network.h"
#include "nspawn-patch-uid.h"
#include "nspawn-register.h"
+#include "nspawn-seccomp.h"
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
#include "nspawn-stub-pid1.h"
-#include "nspawn-seccomp.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
@@ -101,9 +101,11 @@
#include "util.h"
/* Note that devpts's gid= parameter parses GIDs as signed values, hence we stay away from the upper half of the 32bit
- * UID range here */
+ * UID range here. We leave a bit of room at the lower end and a lot of room at the upper end, so that other subsystems
+ * may have their own allocation ranges too. */
#define UID_SHIFT_PICK_MIN ((uid_t) UINT32_C(0x00080000))
#define UID_SHIFT_PICK_MAX ((uid_t) UINT32_C(0x6FFF0000))
+
/* nspawn is listening on the socket at the path in the constant nspawn_notify_socket_path
* nspawn_notify_socket_path is relative to the container
* the init process in the container pid can send messages to nspawn following the sd_notify(3) protocol */
@@ -277,7 +279,6 @@ static void help(void) {
, program_invocation_short_name);
}
-
static int custom_mounts_prepare(void) {
unsigned i;
int r;
@@ -593,9 +594,12 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_UUID:
r = sd_id128_from_string(optarg, &arg_uuid);
- if (r < 0) {
- log_error("Invalid UUID: %s", optarg);
- return r;
+ if (r < 0)
+ return log_error_errno(r, "Invalid UUID: %s", optarg);
+
+ if (sd_id128_is_null(arg_uuid)) {
+ log_error("Machine UUID may not be all zeroes.");
+ return -EINVAL;
}
arg_settings_mask |= SETTING_MACHINE_ID;
@@ -1265,20 +1269,9 @@ static int setup_resolv_conf(const char *dest) {
return 0;
}
-static char* id128_format_as_uuid(sd_id128_t id, char s[37]) {
- assert(s);
-
- snprintf(s, 37,
- "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- SD_ID128_FORMAT_VAL(id));
-
- return s;
-}
-
static int setup_boot_id(const char *dest) {
+ sd_id128_t rnd = SD_ID128_NULL;
const char *from, *to;
- sd_id128_t rnd = {};
- char as_uuid[37];
int r;
if (arg_share_system)
@@ -1294,18 +1287,16 @@ static int setup_boot_id(const char *dest) {
if (r < 0)
return log_error_errno(r, "Failed to generate random boot id: %m");
- id128_format_as_uuid(rnd, as_uuid);
-
- r = write_string_file(from, as_uuid, WRITE_STRING_FILE_CREATE);
+ r = id128_write(from, ID128_UUID, rnd, false);
if (r < 0)
return log_error_errno(r, "Failed to write boot id: %m");
if (mount(from, to, NULL, MS_BIND, NULL) < 0)
r = log_error_errno(errno, "Failed to bind mount boot id: %m");
else if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL) < 0)
- log_warning_errno(errno, "Failed to make boot id read-only: %m");
+ log_warning_errno(errno, "Failed to make boot id read-only, ignoring: %m");
- unlink(from);
+ (void) unlink(from);
return r;
}
@@ -2231,33 +2222,37 @@ static int mount_device(const char *what, const char *where, const char *directo
}
static int setup_machine_id(const char *directory) {
+ const char *etc_machine_id;
+ sd_id128_t id;
int r;
- const char *etc_machine_id, *t;
- _cleanup_free_ char *s = NULL;
- etc_machine_id = prefix_roota(directory, "/etc/machine-id");
+ /* If the UUID in the container is already set, then that's what counts, and we use. If it isn't set, and the
+ * caller passed --uuid=, then we'll pass it in the $container_uuid env var to PID 1 of the container. The
+ * assumption is that PID 1 will then write it to /etc/machine-id to make it persistent. If --uuid= is not
+ * passed we generate a random UUID, and pass it via $container_uuid. In effect this means that /etc/machine-id
+ * in the container and our idea of the container UUID will always be in sync (at least if PID 1 in the
+ * container behaves nicely). */
- r = read_one_line_file(etc_machine_id, &s);
- if (r < 0)
- return log_error_errno(r, "Failed to read machine ID from %s: %m", etc_machine_id);
+ etc_machine_id = prefix_roota(directory, "/etc/machine-id");
- t = strstrip(s);
+ r = id128_read(etc_machine_id, ID128_PLAIN, &id);
+ if (r < 0) {
+ if (!IN_SET(r, -ENOENT, -ENOMEDIUM)) /* If the file is missing or empty, we don't mind */
+ return log_error_errno(r, "Failed to read machine ID from container image: %m");
- if (!isempty(t)) {
- r = sd_id128_from_string(t, &arg_uuid);
- if (r < 0)
- return log_error_errno(r, "Failed to parse machine ID from %s: %m", etc_machine_id);
- } else {
if (sd_id128_is_null(arg_uuid)) {
r = sd_id128_randomize(&arg_uuid);
if (r < 0)
- return log_error_errno(r, "Failed to generate random machine ID: %m");
+ return log_error_errno(r, "Failed to acquire randomized machine UUID: %m");
+ }
+ } else {
+ if (sd_id128_is_null(id)) {
+ log_error("Machine ID in container image is zero, refusing.");
+ return -EINVAL;
}
- }
- r = machine_id_setup(directory, arg_uuid);
- if (r < 0)
- return log_error_errno(r, "Failed to setup machine ID: %m");
+ arg_uuid = id;
+ }
return 0;
}
@@ -2657,7 +2652,7 @@ static int inner_child(
#ifdef HAVE_SELINUX
if (arg_selinux_context)
- if (setexeccon((security_context_t) arg_selinux_context) < 0)
+ if (setexeccon(arg_selinux_context) < 0)
return log_error_errno(errno, "setexeccon(\"%s\") failed: %m", arg_selinux_context);
#endif
@@ -2677,9 +2672,9 @@ static int inner_child(
(asprintf((char**)(envp + n_env++), "LOGNAME=%s", arg_user ? arg_user : "root") < 0))
return log_oom();
- assert(!sd_id128_equal(arg_uuid, SD_ID128_NULL));
+ assert(!sd_id128_is_null(arg_uuid));
- if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_format_as_uuid(arg_uuid, as_uuid)) < 0)
+ if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_to_uuid_string(arg_uuid, as_uuid)) < 0)
return log_oom();
if (fdset_size(fds) > 0) {
@@ -2888,7 +2883,7 @@ static int outer_child(
if (l < 0)
return log_error_errno(errno, "Failed to recv UID shift: %m");
if (l != sizeof(arg_uid_shift)) {
- log_error("Short read while recieving UID shift.");
+ log_error("Short read while receiving UID shift.");
return -EIO;
}
}
@@ -3142,7 +3137,6 @@ static int setup_uid_map(pid_t pid) {
}
static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
- _cleanup_fdset_free_ FDSet *fds = NULL;
char buf[NOTIFY_BUFFER_MAX+1];
char *p = NULL;
struct iovec iovec = {
@@ -3576,7 +3570,7 @@ int main(int argc, char *argv[]) {
}
if (r < 0) {
log_error_errno(r, "Failed to lock %s: %m", arg_directory);
- return r;
+ goto finish;
}
if (arg_template) {