diff options
Diffstat (limited to 'src/home/homework.c')
-rw-r--r-- | src/home/homework.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/src/home/homework.c b/src/home/homework.c index 5907015e2b..ac52a011ed 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -343,6 +343,34 @@ int home_setup_undo_dm(HomeSetup *setup, int level) { return ret; } +int keyring_unlink(key_serial_t k) { + + if (k == -1) /* already invalidated? */ + return -1; + + if (keyctl(KEYCTL_UNLINK, k, KEY_SPEC_SESSION_KEYRING, 0, 0) < 0) + log_debug_errno(errno, "Failed to unlink key from session kernel keyring, ignoring: %m"); + + return -1; /* Always return the key_serial_t value for "invalid" */ +} + +static int keyring_flush(UserRecord *h) { + _cleanup_free_ char *name = NULL; + long serial; + + assert(h); + + name = strjoin("homework-user-", h->user_name); + if (!name) + return log_oom(); + + serial = keyctl(KEYCTL_SEARCH, (unsigned long) KEY_SPEC_SESSION_KEYRING, (unsigned long) "user", (unsigned long) name, 0); + if (serial == -1) + return log_debug_errno(errno, "Failed to find kernel keyring entry for user, ignoring: %m"); + + return keyring_unlink(serial); +} + int home_setup_done(HomeSetup *setup) { int r = 0, q; @@ -393,6 +421,8 @@ int home_setup_done(HomeSetup *setup) { setup->temporary_image_path = mfree(setup->temporary_image_path); } + setup->key_serial = keyring_unlink(setup->key_serial); + setup->undo_mount = false; setup->undo_dm = false; setup->do_offline_fitrim = false; @@ -908,6 +938,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) { static int home_deactivate(UserRecord *h, bool force) { _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT; + _cleanup_(password_cache_free) PasswordCache cache = {}; bool done = false; int r; @@ -943,8 +974,12 @@ static int home_deactivate(UserRecord *h, bool force) { if (r < 0) return r; - if (user_record_storage(h) == USER_LUKS) + if (user_record_storage(h) == USER_LUKS) { + /* Automatically shrink on logout if that's enabled. To be able to shrink we need the + * keys to the device. */ + password_cache_load_keyring(h, &cache); (void) home_trim_luks(h, &setup); + } /* Sync explicitly, so that the drop caches logic below can work as documented */ if (syncfs(setup.root_fd) < 0) @@ -952,6 +987,9 @@ static int home_deactivate(UserRecord *h, bool force) { else log_info("Syncing completed."); + if (user_record_storage(h) == USER_LUKS) + (void) home_auto_shrink_luks(h, &setup, &cache); + setup.root_fd = safe_close(setup.root_fd); /* Now get rid of the bind mount, too */ @@ -977,6 +1015,9 @@ static int home_deactivate(UserRecord *h, bool force) { done = true; } + /* Explicitly flush any per-user key from the keyring */ + (void) keyring_flush(h); + if (!done) return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home is not active."); @@ -1656,7 +1697,7 @@ static int home_passwd(UserRecord *h, UserRecord **ret_home) { switch (user_record_storage(h)) { case USER_LUKS: - r = home_passwd_luks(h, &setup, &cache, effective_passwords); + r = home_passwd_luks(h, flags, &setup, &cache, effective_passwords); if (r < 0) return r; break; |