diff options
Diffstat (limited to 'src/machine/machine-dbus.c')
-rw-r--r-- | src/machine/machine-dbus.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index af745b6567..36568b65ef 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -411,7 +411,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s if (fd < 0) _exit(EXIT_FAILURE); - r = copy_bytes(fd, pair[1], (uint64_t) -1, false); + r = copy_bytes(fd, pair[1], (uint64_t) -1, 0); if (r < 0) _exit(EXIT_FAILURE); @@ -841,6 +841,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu int read_only, make_directory; pid_t child; siginfo_t si; + uid_t uid; int r; assert(message); @@ -875,6 +876,12 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu if (r == 0) return 1; /* Will call us back */ + r = machine_get_uid_shift(m, &uid); + if (r < 0) + return r; + if (uid != 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Can't bind mount on container with user namespacing applied."); + /* One day, when bind mounting /proc/self/fd/n works across * namespace boundaries we should rework this logic to make * use of it... */ @@ -1055,10 +1062,12 @@ finish: int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname; _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE; _cleanup_close_ int hostfd = -1; Machine *m = userdata; bool copy_from; pid_t child; + uid_t uid_shift; char *t; int r; @@ -1097,6 +1106,10 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro if (r == 0) return 1; /* Will call us back */ + r = machine_get_uid_shift(m, &uid_shift); + if (r < 0) + return r; + copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom"); if (copy_from) { @@ -1151,10 +1164,13 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro goto child_fail; } + /* Run the actual copy operation. Note that when an UID shift is set we'll either clamp the UID/GID to + * 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy + * the UID/GIDs as they are. */ if (copy_from) - r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true); + r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags); else - r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true); + r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags); hostfd = safe_close(hostfd); containerfd = safe_close(containerfd); @@ -1276,6 +1292,32 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda return sd_bus_reply_method_return(message, "h", fd); } +int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Machine *m = userdata; + uid_t shift = 0; + int r; + + assert(message); + assert(m); + + /* You wonder why this is a method and not a property? Well, properties are not supposed to return errors, but + * we kinda have to for this. */ + + if (m->class == MACHINE_HOST) + return sd_bus_reply_method_return(message, "u", UINT32_C(0)); + + if (m->class != MACHINE_CONTAINER) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "UID/GID shift may only be determined for container machines."); + + r = machine_get_uid_shift(m, &shift); + if (r == -ENXIO) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Machine %s uses a complex UID/GID mapping, cannot determine shift", m->name); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "u", (uint32_t) shift); +} + const sd_bus_vtable machine_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1293,6 +1335,7 @@ const sd_bus_vtable machine_vtable[] = { SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUIDShift", NULL, "u", bus_machine_method_get_uid_shift, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("OpenShell", "ssasas", "hs", bus_machine_method_open_shell, SD_BUS_VTABLE_UNPRIVILEGED), |