summaryrefslogtreecommitdiff
path: root/src/nspawn/nspawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r--src/nspawn/nspawn.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 7fa098bea8..3428109da4 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -341,6 +341,11 @@ static int custom_mounts_prepare(void) {
for (i = 0; i < arg_n_custom_mounts; i++) {
CustomMount *m = &arg_custom_mounts[i];
+ if (arg_userns && arg_uid_shift == UID_INVALID && path_equal(m->destination, "/")) {
+ log_error("--private-users with automatic UID shift may not be combined with custom root mounts.");
+ return -EINVAL;
+ }
+
if (m->type != CUSTOM_MOUNT_OVERLAY)
continue;
@@ -751,9 +756,8 @@ static int parse_argv(int argc, char *argv[]) {
/* If two parameters are specified,
* the first one is the lower, the
* second one the upper directory. And
- * we'll also define the the
- * destination mount point the same as
- * the upper. */
+ * we'll also define the destination
+ * mount point the same as the upper. */
upper = lower[1];
lower[1] = NULL;
@@ -1028,6 +1032,7 @@ static int tmpfs_patch_options(const char *options, char **ret) {
char *buf = NULL;
if (arg_userns && arg_uid_shift != 0) {
+ assert(arg_uid_shift != UID_INVALID);
if (options)
(void) asprintf(&buf, "%s,uid=" UID_FMT ",gid=" UID_FMT, options, arg_uid_shift, arg_uid_shift);
@@ -1697,7 +1702,7 @@ static int setup_boot_id(const char *dest) {
id128_format_as_uuid(rnd, as_uuid);
- r = write_string_file(from, as_uuid);
+ r = write_string_file(from, as_uuid, WRITE_STRING_FILE_CREATE);
if (r < 0)
return log_error_errno(r, "Failed to write boot id: %m");
@@ -2273,7 +2278,7 @@ static int drop_capabilities(void) {
static int register_machine(pid_t pid, int local_ifindex) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
if (!arg_register)
@@ -2430,7 +2435,7 @@ static int register_machine(pid_t pid, int local_ifindex) {
static int terminate_machine(pid_t pid) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
const char *path;
int r;
@@ -2502,7 +2507,7 @@ static int reset_audit_loginuid(void) {
if (streq(p, "4294967295"))
return 0;
- r = write_string_file("/proc/self/loginuid", "4294967295");
+ r = write_string_file("/proc/self/loginuid", "4294967295", 0);
if (r < 0) {
log_error_errno(r,
"Failed to reset audit login UID. This probably means that your kernel is too\n"
@@ -4259,6 +4264,7 @@ static int outer_child(
int pid_socket,
int kmsg_socket,
int rtnl_socket,
+ int uid_shift_socket,
FDSet *fds,
int argc,
char *argv[]) {
@@ -4313,6 +4319,20 @@ static int outer_child(
if (r < 0)
return r;
+ r = determine_uid_shift(directory);
+ if (r < 0)
+ return r;
+
+ if (arg_userns) {
+ l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL);
+ if (l < 0)
+ return log_error_errno(errno, "Failed to send UID shift: %m");
+ if (l != sizeof(arg_uid_shift)) {
+ log_error("Short write while sending UID shift.");
+ return -EIO;
+ }
+ }
+
/* Turn directory into bind mount */
if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0)
return log_error_errno(errno, "Failed to make bind mount: %m");
@@ -4393,6 +4413,7 @@ static int outer_child(
if (pid == 0) {
pid_socket = safe_close(pid_socket);
+ uid_shift_socket = safe_close(uid_shift_socket);
/* The inner child has all namespaces that are
* requested, so that we all are owned by the user if
@@ -4426,13 +4447,13 @@ static int setup_uid_map(pid_t pid) {
xsprintf(uid_map, "/proc/" PID_FMT "/uid_map", pid);
xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, arg_uid_shift, arg_uid_range);
- r = write_string_file(uid_map, line);
+ r = write_string_file(uid_map, line, 0);
if (r < 0)
return log_error_errno(r, "Failed to write UID map: %m");
/* We always assign the same UID and GID ranges */
xsprintf(uid_map, "/proc/" PID_FMT "/gid_map", pid);
- r = write_string_file(uid_map, line);
+ r = write_string_file(uid_map, line, 0);
if (r < 0)
return log_error_errno(r, "Failed to write GID map: %m");
@@ -4491,10 +4512,6 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- r = determine_uid_shift(arg_directory);
- if (r < 0)
- return r;
-
if (geteuid() != 0) {
log_error("Need to be root.");
r = -EPERM;
@@ -4687,7 +4704,8 @@ int main(int argc, char *argv[]) {
}
for (;;) {
- _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 };
+ _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 },
+ uid_shift_socket_pair[2] = { -1, -1 };
ContainerStatus container_status;
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
static const struct sigaction sa = {
@@ -4696,10 +4714,10 @@ int main(int argc, char *argv[]) {
};
int ifi = 0;
ssize_t l;
- _cleanup_event_unref_ sd_event *event = NULL;
- _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
- _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
- char last_char = 0;
+ _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
+ _cleanup_netlink_unref_ sd_netlink *rtnl = NULL;
+ char last_char = 0;
r = barrier_create(&barrier);
if (r < 0) {
@@ -4722,6 +4740,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ if (arg_userns)
+ if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) {
+ r = log_error_errno(errno, "Failed to create uid shift socket pair: %m");
+ goto finish;
+ }
+
/* Child can be killed before execv(), so handle SIGCHLD
* in order to interrupt parent's blocking calls and
* give it a chance to call wait() and terminate. */
@@ -4756,6 +4780,7 @@ int main(int argc, char *argv[]) {
kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]);
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
pid_socket_pair[0] = safe_close(pid_socket_pair[0]);
+ uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]);
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
@@ -4771,6 +4796,7 @@ int main(int argc, char *argv[]) {
pid_socket_pair[1],
kmsg_socket_pair[1],
rtnl_socket_pair[1],
+ uid_shift_socket_pair[1],
fds,
argc, argv);
if (r < 0)
@@ -4819,6 +4845,17 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof(arg_uid_shift), 0);
+ if (l < 0) {
+ r = log_error_errno(errno, "Failed to read UID shift: %m");
+ goto finish;
+ }
+ if (l != sizeof(arg_uid_shift)) {
+ log_error("Short read while reading UID shift: %m");
+ r = EIO;
+ goto finish;
+ }
+
r = setup_uid_map(pid);
if (r < 0)
goto finish;