homework: teach luks backend uid mapping

This teachs the LUKS backend UID mapping, similar to the existing
logic for the "directory", "subvolume" and "fscrypt" backends: the files
will be owned by "nobody" on the fs itself, but will be mapped to
logging in user via uidmapped mounts.

This way LUKS home dirs become truly portable: no local UID info will
leak onto the images anymore, and the need to recursively chown them on
activation goes away. This means activation is always as performant as
it should be.
This commit is contained in:
Lennart Poettering 2021-10-26 18:34:57 +02:00
parent a2bc39786a
commit 1147c538bb
3 changed files with 37 additions and 6 deletions

View file

@ -45,6 +45,7 @@
#include "strv.h"
#include "sync-util.h"
#include "tmpfile-util.h"
#include "user-util.h"
/* Round down to the nearest 4K size. Given that newer hardware generally prefers 4K sectors, let's align our
* partitions to that too. In the worst case we'll waste 3.5K per partition that way, but I think I can live
@ -1989,6 +1990,7 @@ int home_create_luks(
host_size = 0, partition_offset = 0, partition_size = 0; /* Unnecessary initialization to appease gcc */
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
sd_id128_t partition_uuid, fs_uuid, luks_uuid, disk_uuid;
_cleanup_close_ int mount_fd = -1;
const char *fstype, *ip;
struct statfs sfs;
int r;
@ -2237,6 +2239,19 @@ int home_create_luks(
if (setup->root_fd < 0)
return log_error_errno(errno, "Failed to open user directory in mounted image file: %m");
(void) home_shift_uid(setup->root_fd, NULL, UID_NOBODY, h->uid, &mount_fd);
if (mount_fd >= 0) {
/* If we have established a new mount, then we can use that as new root fd to our home directory. */
safe_close(setup->root_fd);
setup->root_fd = fd_reopen(mount_fd, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
if (setup->root_fd < 0)
return log_error_errno(setup->root_fd, "Unable to convert mount fd into proper directory fd: %m");
mount_fd = safe_close(mount_fd);
}
r = home_populate(h, setup->root_fd);
if (r < 0)
return r;

View file

@ -84,7 +84,17 @@ int home_unshare_and_mount(const char *node, const char *fstype, bool discard, u
if (r < 0)
return r;
return home_mount_node(node, fstype, discard, flags);
r = home_mount_node(node, fstype, discard, flags);
if (r < 0)
return r;
r = mount_nofollow_verbose(LOG_ERR, NULL, HOME_RUNTIME_WORK_DIR, NULL, MS_PRIVATE, NULL);
if (r < 0) {
(void) umount_verbose(LOG_ERR, HOME_RUNTIME_WORK_DIR, UMOUNT_NOFOLLOW);
return r;
}
return 0;
}
int home_move_mount(const char *mount_suffix, const char *target) {
@ -111,9 +121,9 @@ int home_move_mount(const char *mount_suffix, const char *target) {
if (r < 0)
return r;
r = umount_verbose(LOG_ERR, HOME_RUNTIME_WORK_DIR, UMOUNT_NOFOLLOW);
r = umount_recursive(HOME_RUNTIME_WORK_DIR, 0);
if (r < 0)
return r;
return log_error_errno(r, "Failed to unmount %s: %m", HOME_RUNTIME_WORK_DIR);
log_info("Moving to final mount point %s completed.", target);
return 0;

View file

@ -306,9 +306,15 @@ int home_setup_undo_mount(HomeSetup *setup, int level) {
if (!setup->undo_mount)
return 0;
r = umount_verbose(level, HOME_RUNTIME_WORK_DIR, UMOUNT_NOFOLLOW);
if (r < 0)
return r;
r = umount_recursive(HOME_RUNTIME_WORK_DIR, 0);
if (r < 0) {
if (level >= LOG_DEBUG) /* umount_recursive() does debug level logging anyway, no need to
* repeat that here */
return r;
/* If a higher log level is requested, the generate a non-debug mesage here too. */
return log_full_errno(level, r, "Failed to unmount mount tree below %s: %m", HOME_RUNTIME_WORK_DIR);
}
setup->undo_mount = false;
return 1;