dissect-image: add support for optionally mounting images with idmapping on
This commit is contained in:
@@ -2170,7 +2170,7 @@ int setup_namespace(
|
||||
|
||||
if (root_image) {
|
||||
/* A root image is specified, mount it to the right place */
|
||||
r = dissected_image_mount(dissected_image, root, UID_INVALID, dissect_image_flags);
|
||||
r = dissected_image_mount(dissected_image, root, UID_INVALID, UID_INVALID, dissect_image_flags);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to mount root image: %m");
|
||||
goto finish;
|
||||
|
||||
@@ -582,7 +582,7 @@ static int action_mount(DissectedImage *m, LoopDevice *d) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dissected_image_mount_and_warn(m, arg_path, UID_INVALID, arg_flags);
|
||||
r = dissected_image_mount_and_warn(m, arg_path, UID_INVALID, UID_INVALID, arg_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -628,7 +628,7 @@ static int action_copy(DissectedImage *m, LoopDevice *d) {
|
||||
|
||||
created_dir = TAKE_PTR(temp);
|
||||
|
||||
r = dissected_image_mount_and_warn(m, created_dir, UID_INVALID, arg_flags);
|
||||
r = dissected_image_mount_and_warn(m, created_dir, UID_INVALID, UID_INVALID, arg_flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -3605,6 +3605,7 @@ static int outer_child(
|
||||
dissected_image,
|
||||
directory,
|
||||
arg_uid_shift,
|
||||
arg_uid_range,
|
||||
DISSECT_IMAGE_MOUNT_ROOT_ONLY|
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP|
|
||||
DISSECT_IMAGE_USR_NO_ROOT|
|
||||
@@ -3696,6 +3697,7 @@ static int outer_child(
|
||||
dissected_image,
|
||||
directory,
|
||||
arg_uid_shift,
|
||||
arg_uid_range,
|
||||
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP|
|
||||
DISSECT_IMAGE_USR_NO_ROOT|
|
||||
|
||||
@@ -426,7 +426,7 @@ static int portable_extract_by_path(
|
||||
if (r == 0) {
|
||||
seq[0] = safe_close(seq[0]);
|
||||
|
||||
r = dissected_image_mount(m, tmpdir, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
|
||||
r = dissected_image_mount(m, tmpdir, UID_INVALID, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to mount dissected image: %m");
|
||||
goto child_finish;
|
||||
|
||||
+45
-21
@@ -1472,11 +1472,12 @@ static int mount_partition(
|
||||
const char *where,
|
||||
const char *directory,
|
||||
uid_t uid_shift,
|
||||
uid_t uid_range,
|
||||
DissectImageFlags flags) {
|
||||
|
||||
_cleanup_free_ char *chased = NULL, *options = NULL;
|
||||
const char *p, *node, *fstype;
|
||||
bool rw;
|
||||
bool rw, remap_uid_gid = false;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@@ -1536,14 +1537,18 @@ static int mount_partition(
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (uid_is_valid(uid_shift) && uid_shift != 0 && fstype_can_uid_gid(fstype)) {
|
||||
_cleanup_free_ char *uid_option = NULL;
|
||||
if (uid_is_valid(uid_shift) && uid_shift != 0) {
|
||||
|
||||
if (asprintf(&uid_option, "uid=" UID_FMT ",gid=" GID_FMT, uid_shift, (gid_t) uid_shift) < 0)
|
||||
return -ENOMEM;
|
||||
if (fstype_can_uid_gid(fstype)) {
|
||||
_cleanup_free_ char *uid_option = NULL;
|
||||
|
||||
if (!strextend_with_separator(&options, ",", uid_option))
|
||||
return -ENOMEM;
|
||||
if (asprintf(&uid_option, "uid=" UID_FMT ",gid=" GID_FMT, uid_shift, (gid_t) uid_shift) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strextend_with_separator(&options, ",", uid_option))
|
||||
return -ENOMEM;
|
||||
} else if (FLAGS_SET(flags, DISSECT_IMAGE_MOUNT_IDMAPPED))
|
||||
remap_uid_gid = true;
|
||||
}
|
||||
|
||||
if (!isempty(m->mount_options))
|
||||
@@ -1578,6 +1583,12 @@ static int mount_partition(
|
||||
if (rw && m->growfs && FLAGS_SET(flags, DISSECT_IMAGE_GROWFS))
|
||||
(void) fs_grow(node, p);
|
||||
|
||||
if (remap_uid_gid) {
|
||||
r = remount_idmap(p, uid_shift, uid_range);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1607,7 +1618,13 @@ static int mount_root_tmpfs(const char *where, uid_t uid_shift, DissectImageFlag
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) {
|
||||
int dissected_image_mount(
|
||||
DissectedImage *m,
|
||||
const char *where,
|
||||
uid_t uid_shift,
|
||||
uid_t uid_range,
|
||||
DissectImageFlags flags) {
|
||||
|
||||
int r, xbootldr_mounted;
|
||||
|
||||
assert(m);
|
||||
@@ -1631,14 +1648,14 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
|
||||
|
||||
/* First mount the root fs. If there's none we use a tmpfs. */
|
||||
if (m->partitions[PARTITION_ROOT].found)
|
||||
r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, uid_range, flags);
|
||||
else
|
||||
r = mount_root_tmpfs(where, uid_shift, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* For us mounting root always means mounting /usr as well */
|
||||
r = mount_partition(m->partitions + PARTITION_USR, where, "/usr", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_USR, where, "/usr", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1659,23 +1676,23 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
|
||||
if (flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY)
|
||||
return 0;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_VAR, where, "/var", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_VAR, where, "/var", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_TMP, where, "/var/tmp", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_TMP, where, "/var/tmp", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
xbootldr_mounted = mount_partition(m->partitions + PARTITION_XBOOTLDR, where, "/boot", uid_shift, flags);
|
||||
xbootldr_mounted = mount_partition(m->partitions + PARTITION_XBOOTLDR, where, "/boot", uid_shift, uid_range, flags);
|
||||
if (xbootldr_mounted < 0)
|
||||
return xbootldr_mounted;
|
||||
|
||||
@@ -1701,7 +1718,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
|
||||
return r;
|
||||
} else if (dir_is_empty(p) > 0) {
|
||||
/* It exists and is an empty directory. Let's mount the ESP there. */
|
||||
r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1713,7 +1730,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
|
||||
if (!esp_done) {
|
||||
/* OK, let's mount the ESP now to /efi (possibly creating the dir if missing) */
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, uid_range, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -1722,13 +1739,19 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) {
|
||||
int dissected_image_mount_and_warn(
|
||||
DissectedImage *m,
|
||||
const char *where,
|
||||
uid_t uid_shift,
|
||||
uid_t uid_range,
|
||||
DissectImageFlags flags) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(where);
|
||||
|
||||
r = dissected_image_mount(m, where, uid_shift, flags);
|
||||
r = dissected_image_mount(m, where, uid_shift, uid_range, flags);
|
||||
if (r == -ENXIO)
|
||||
return log_error_errno(r, "Not root file system found in image.");
|
||||
if (r == -EMEDIUMTYPE)
|
||||
@@ -2523,6 +2546,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
|
||||
m,
|
||||
t,
|
||||
UID_INVALID,
|
||||
UID_INVALID,
|
||||
DISSECT_IMAGE_READ_ONLY|
|
||||
DISSECT_IMAGE_MOUNT_ROOT_ONLY|
|
||||
DISSECT_IMAGE_VALIDATE_OS|
|
||||
@@ -2811,7 +2835,7 @@ int mount_image_privately_interactively(
|
||||
|
||||
created_dir = TAKE_PTR(temp);
|
||||
|
||||
r = dissected_image_mount_and_warn(dissected_image, created_dir, UID_INVALID, flags);
|
||||
r = dissected_image_mount_and_warn(dissected_image, created_dir, UID_INVALID, UID_INVALID, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2917,7 +2941,7 @@ int verity_dissect_and_mount(
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to umount under destination directory %s: %m", dest);
|
||||
|
||||
r = dissected_image_mount(dissected_image, dest, UID_INVALID, dissect_image_flags);
|
||||
r = dissected_image_mount(dissected_image, dest, UID_INVALID, UID_INVALID, dissect_image_flags);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to mount image: %m");
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ typedef enum DissectImageFlags {
|
||||
DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY |
|
||||
DISSECT_IMAGE_MOUNT_READ_ONLY,
|
||||
DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
|
||||
DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file sytem type doesn't support uid=/gid= */
|
||||
} DissectImageFlags;
|
||||
|
||||
struct DissectedImage {
|
||||
@@ -169,8 +170,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
|
||||
|
||||
int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags, DecryptedImage **ret);
|
||||
int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags, DecryptedImage **ret);
|
||||
int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, DissectImageFlags flags);
|
||||
int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags);
|
||||
int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, uid_t uid_range, DissectImageFlags flags);
|
||||
int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, uid_t uid_range, DissectImageFlags flags);
|
||||
|
||||
int dissected_image_acquire_metadata(DissectedImage *m);
|
||||
|
||||
|
||||
@@ -551,6 +551,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
m,
|
||||
p,
|
||||
UID_INVALID,
|
||||
UID_INVALID,
|
||||
flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -77,7 +77,7 @@ static void* thread_func(void *ptr) {
|
||||
assert_se(dissected->partitions[PARTITION_HOME].found);
|
||||
assert_se(dissected->partitions[PARTITION_HOME].node);
|
||||
|
||||
r = dissected_image_mount(dissected, mounted, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
|
||||
r = dissected_image_mount(dissected, mounted, UID_INVALID, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
|
||||
log_notice_errno(r, "Mounted %s → %s: %m", loop->node, mounted);
|
||||
assert_se(r >= 0);
|
||||
|
||||
@@ -217,7 +217,7 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
|
||||
|
||||
/* This first (writable) mount will initialize the mount point dirs, so that the subsequent read-only ones can work */
|
||||
assert_se(dissected_image_mount(dissected, mounted, UID_INVALID, 0) >= 0);
|
||||
assert_se(dissected_image_mount(dissected, mounted, UID_INVALID, UID_INVALID, 0) >= 0);
|
||||
|
||||
assert_se(umount_recursive(mounted, 0) >= 0);
|
||||
loop = loop_device_unref(loop);
|
||||
|
||||
Reference in New Issue
Block a user