From 6b356f4498730d613ce0b0618b79c09e3261089b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Nov 2021 18:26:28 +0100 Subject: [PATCH 1/6] homectl: also acquire "cheap" passwords for homectl update/passwd In 57bb9bcba5563c040ee0c41f58e3730a006a8de2 support was added to read "cheap" passwords from env vars and stuff before issuing the first operation, instead of waiting for it until the first operation failed. This was added for most verbs of "homectl", but two were left out: update + passwd. Add it there too. --- src/home/homectl.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/home/homectl.c b/src/home/homectl.c index cc2b9c8f31..706ce75dfb 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -1535,7 +1535,7 @@ static int home_record_reset_human_interaction_permission(UserRecord *hr) { static int update_home(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(user_record_unrefp) UserRecord *hr = NULL; + _cleanup_(user_record_unrefp) UserRecord *hr = NULL, *secret = NULL; _cleanup_free_ char *buffer = NULL; const char *username; int r; @@ -1561,6 +1561,15 @@ static int update_home(int argc, char *argv[], void *userdata) { if (r < 0) return r; + /* Add in all secrets we can acquire cheaply */ + r = acquire_passed_secrets(username, &secret); + if (r < 0) + return r; + + r = user_record_merge_secret(hr, secret); + if (r < 0) + return r; + /* If we do multiple operations, let's output things more verbosely, since otherwise the repeated * authentication might be confusing. */ @@ -1706,9 +1715,9 @@ static int passwd_home(int argc, char *argv[], void *userdata) { (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); - old_secret = user_record_new(); - if (!old_secret) - return log_oom(); + r = acquire_passed_secrets(username, &old_secret); + if (r < 0) + return r; new_secret = user_record_new(); if (!new_secret) From eae3a68144d9825535b22db0bbb06a024a0b4400 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Nov 2021 18:29:52 +0100 Subject: [PATCH 2/6] homework: fix message typo --- src/home/homework-luks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index ac379c6d07..529796ad9c 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -428,7 +428,7 @@ static int luks_setup( if (r == -ENOKEY) return log_error_errno(r, "No valid password for LUKS superblock."); if (r < 0) - return log_error_errno(r, "Failed to unlocks LUKS superblock: %m"); + return log_error_errno(r, "Failed to unlock LUKS superblock: %m"); r = sym_crypt_activate_by_volume_key( cd, From 6f2c813667018cc54f127a15a578a74071b0fa24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Nov 2021 18:31:51 +0100 Subject: [PATCH 3/6] homework: don't try to shift uidmap for already activated home areas When we want to operate on an already activated home area we so far tried to reapply the uidmapping logic. We shouldn't do that, it's already applied after all. We only want to apply this for newly activated home areas. Hence check for the right HomeSetupFlags flag for it HOME_SETUP_ALREADY_ACTIVATED. The patch is actually in theory a two-liner. Except that so far we don#t pass the HomeSetupFlags flags down all necessary functions where the uidmap stuff will eventually run. Hence this larger than intended commit. --- src/home/homework-cifs.c | 3 ++- src/home/homework-cifs.h | 2 +- src/home/homework-directory.c | 7 ++++--- src/home/homework-directory.h | 2 +- src/home/homework-luks.c | 2 ++ src/home/homework-luks.h | 2 +- src/home/homework.c | 15 +++++++++++---- src/home/homework.h | 4 ++-- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/home/homework-cifs.c b/src/home/homework-cifs.c index b49b7b3dcd..ed06d1f221 100644 --- a/src/home/homework-cifs.c +++ b/src/home/homework-cifs.c @@ -145,6 +145,7 @@ int home_setup_cifs( int home_activate_cifs( UserRecord *h, + HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home) { @@ -165,7 +166,7 @@ int home_activate_cifs( if (r < 0) return r; - r = home_refresh(h, setup, header_home, cache, NULL, &new_home); + r = home_refresh(h, flags, setup, header_home, cache, NULL, &new_home); if (r < 0) return r; diff --git a/src/home/homework-cifs.h b/src/home/homework-cifs.h index dda1e0b876..af8c466629 100644 --- a/src/home/homework-cifs.h +++ b/src/home/homework-cifs.h @@ -6,6 +6,6 @@ int home_setup_cifs(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup); -int home_activate_cifs(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); +int home_activate_cifs(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); int home_create_cifs(UserRecord *h, HomeSetup *setup, UserRecord **ret_home); diff --git a/src/home/homework-directory.c b/src/home/homework-directory.c index af13fa026a..c2b383b7cd 100644 --- a/src/home/homework-directory.c +++ b/src/home/homework-directory.c @@ -58,6 +58,7 @@ int home_setup_directory(UserRecord *h, HomeSetup *setup) { int home_activate_directory( UserRecord *h, + HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home) { @@ -74,11 +75,11 @@ int home_activate_directory( assert_se(hdo = user_record_home_directory(h)); hd = strdupa_safe(hdo); - r = home_setup(h, 0, setup, cache, &header_home); + r = home_setup(h, flags, setup, cache, &header_home); if (r < 0) return r; - r = home_refresh(h, setup, header_home, cache, NULL, &new_home); + r = home_refresh(h, flags, setup, header_home, cache, NULL, &new_home); if (r < 0) return r; @@ -279,7 +280,7 @@ int home_resize_directory( if (r < 0) return r; - r = home_maybe_shift_uid(h, setup); + r = home_maybe_shift_uid(h, flags, setup); if (r < 0) return r; diff --git a/src/home/homework-directory.h b/src/home/homework-directory.h index ecbb2f143c..fe03e5deb1 100644 --- a/src/home/homework-directory.h +++ b/src/home/homework-directory.h @@ -5,6 +5,6 @@ #include "user-record.h" int home_setup_directory(UserRecord *h, HomeSetup *setup); -int home_activate_directory(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); +int home_activate_directory(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); int home_create_directory_or_subvolume(UserRecord *h, HomeSetup *setup, UserRecord **ret_home); int home_resize_directory(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 529796ad9c..2e1c4c6170 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -1511,6 +1511,7 @@ static int home_auto_grow_luks( int home_activate_luks( UserRecord *h, + HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home) { @@ -1563,6 +1564,7 @@ int home_activate_luks( r = home_refresh( h, + flags, setup, luks_home_record, cache, diff --git a/src/home/homework-luks.h b/src/home/homework-luks.h index f0f29b78f7..0218de8ccd 100644 --- a/src/home/homework-luks.h +++ b/src/home/homework-luks.h @@ -7,7 +7,7 @@ int home_setup_luks(UserRecord *h, HomeSetupFlags flags, const char *force_image_path, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_luks_home); -int home_activate_luks(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); +int home_activate_luks(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); int home_deactivate_luks(UserRecord *h, HomeSetup *setup); int home_trim_luks(UserRecord *h, HomeSetup *setup); diff --git a/src/home/homework.c b/src/home/homework.c index ac52a011ed..864171faed 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -788,6 +788,7 @@ static int chown_recursive_directory(int root_fd, uid_t uid) { int home_maybe_shift_uid( UserRecord *h, + HomeSetupFlags flags, HomeSetup *setup) { _cleanup_close_ int mount_fd = -1; @@ -797,6 +798,10 @@ int home_maybe_shift_uid( assert(setup); assert(setup->root_fd >= 0); + /* If the home dir is already activated, then the UID shift is already applied. */ + if (FLAGS_SET(flags, HOME_SETUP_ALREADY_ACTIVATED)) + return 0; + if (fstat(setup->root_fd, &st) < 0) return log_error_errno(errno, "Failed to stat() home directory: %m"); @@ -820,6 +825,7 @@ int home_maybe_shift_uid( int home_refresh( UserRecord *h, + HomeSetupFlags flags, HomeSetup *setup, UserRecord *header_home, PasswordCache *cache, @@ -840,7 +846,7 @@ int home_refresh( if (r < 0) return r; - r = home_maybe_shift_uid(h, setup); + r = home_maybe_shift_uid(h, flags, setup); if (r < 0) return r; @@ -868,6 +874,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) { _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL; _cleanup_(password_cache_free) PasswordCache cache = {}; + HomeSetupFlags flags = 0; int r; assert(h); @@ -898,7 +905,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) { switch (user_record_storage(h)) { case USER_LUKS: - r = home_activate_luks(h, &setup, &cache, &new_home); + r = home_activate_luks(h, flags, &setup, &cache, &new_home); if (r < 0) return r; @@ -907,14 +914,14 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) { case USER_SUBVOLUME: case USER_DIRECTORY: case USER_FSCRYPT: - r = home_activate_directory(h, &setup, &cache, &new_home); + r = home_activate_directory(h, flags, &setup, &cache, &new_home); if (r < 0) return r; break; case USER_CIFS: - r = home_activate_cifs(h, &setup, &cache, &new_home); + r = home_activate_cifs(h, flags, &setup, &cache, &new_home); if (r < 0) return r; diff --git a/src/home/homework.h b/src/home/homework.h index 750ad331c8..882a3f500b 100644 --- a/src/home/homework.h +++ b/src/home/homework.h @@ -80,9 +80,9 @@ int keyring_unlink(key_serial_t k); int home_setup(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_header_home); -int home_refresh(UserRecord *h, HomeSetup *setup, UserRecord *header_home, PasswordCache *cache, struct statfs *ret_statfs, UserRecord **ret_new_home); +int home_refresh(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup, UserRecord *header_home, PasswordCache *cache, struct statfs *ret_statfs, UserRecord **ret_new_home); -int home_maybe_shift_uid(UserRecord *h, HomeSetup *setup); +int home_maybe_shift_uid(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup); int home_populate(UserRecord *h, int dir_fd); int home_load_embedded_identity(UserRecord *h, int root_fd, UserRecord *header_home, UserReconcileMode mode, PasswordCache *cache, UserRecord **ret_embedded_home, UserRecord **ret_new_home); From a8be09840365e46ea17160aaea1925d34a8432bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Nov 2021 18:34:02 +0100 Subject: [PATCH 4/6] homework: also apply uid shifting when changing passwords/resizing/updating home areas This adds uidmap shifting also when resizing/updating/changing passwords. Prviously I thought we didn't have to, because the user is not going to access the uidmap if we only quickly activate the home area. But this thinking is wrong, because the three operations will result in an update ~/.identity fie to be written, and we should do that with uidmap applied, so that its ownership maps down to nobody below as intended. Fixes: #21441 --- src/home/homework-luks.c | 4 ++++ src/home/homework.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 2e1c4c6170..29a18b48d9 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -3202,6 +3202,10 @@ int home_resize_luks( return r; } + r = home_maybe_shift_uid(h, flags, setup); + if (r < 0) + return r; + log_info("offset = %" PRIu64 ", size = %" PRIu64 ", image = %" PRIu64, setup->partition_offset, setup->partition_size, old_image_size); if ((UINT64_MAX - setup->partition_offset) < setup->partition_size || diff --git a/src/home/homework.c b/src/home/homework.c index 864171faed..d2a24d3210 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -1609,6 +1609,10 @@ static int home_update(UserRecord *h, UserRecord **ret) { if (r < 0) return r; + r = home_maybe_shift_uid(h, flags, &setup); + if (r < 0) + return r; + r = home_store_header_identity_luks(new_home, &setup, header_home); if (r < 0) return r; @@ -1701,6 +1705,10 @@ static int home_passwd(UserRecord *h, UserRecord **ret_home) { if (r < 0) return r; + r = home_maybe_shift_uid(h, flags, &setup); + if (r < 0) + return r; + switch (user_record_storage(h)) { case USER_LUKS: From b05f4495bd374dc28d39ea43ac7cec3f0fea4071 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Nov 2021 18:36:00 +0100 Subject: [PATCH 5/6] homework: fix a bad error propagation --- src/home/homework.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/homework.c b/src/home/homework.c index d2a24d3210..520b6b6f06 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -585,7 +585,7 @@ static int write_identity_file(int root_fd, JsonVariant *v, uid_t uid) { } if (fchown(fileno(identity_file), uid, uid) < 0) { - log_error_errno(r, "Failed to change ownership of identity file: %m"); + r = log_error_errno(errno, "Failed to change ownership of identity file: %m"); goto fail; } From 6c68d5ad731da6e2d5d1c0c8ddfe536faaca8830 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Nov 2021 18:40:36 +0100 Subject: [PATCH 6/6] homework: add debug log message whenever we applied a uidmap to a mount --- src/home/homework-mount.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/home/homework-mount.c b/src/home/homework-mount.c index 1e63dbed41..0b028dad37 100644 --- a/src/home/homework-mount.c +++ b/src/home/homework-mount.c @@ -283,6 +283,8 @@ int home_shift_uid(int dir_fd, const char *target, uid_t stored_uid, uid_t expos if (r < 0) return log_error_errno(errno, "Failed to apply UID/GID map: %m"); + log_debug("Applied uidmap mount to %s. Mapping is " UID_FMT " → " UID_FMT ".", strna(target), stored_uid, exposed_uid); + if (ret_mount_fd) *ret_mount_fd = TAKE_FD(mount_fd);