mirror of
https://github.com/systemd/systemd
synced 2024-10-06 16:21:34 +00:00
Merge pull request #33189 from bluca/fscrypt_flush
homed: flush fscrypt key on lock/deactivate
This commit is contained in:
commit
b06ab6b92b
|
@ -33,3 +33,34 @@ int keyring_read(key_serial_t serial, void **ret, size_t *ret_size) {
|
|||
bufsize = (size_t) n;
|
||||
}
|
||||
}
|
||||
|
||||
int keyring_describe(key_serial_t serial, char **ret) {
|
||||
_cleanup_free_ char *tuple = NULL;
|
||||
size_t sz = 64;
|
||||
int c = -1; /* Workaround for maybe-uninitialized false positive due to missing_syscall indirection */
|
||||
|
||||
assert(ret);
|
||||
|
||||
for (;;) {
|
||||
tuple = new(char, sz);
|
||||
if (!tuple)
|
||||
return log_oom_debug();
|
||||
|
||||
c = keyctl(KEYCTL_DESCRIBE, serial, (unsigned long) tuple, c, 0);
|
||||
if (c < 0)
|
||||
return log_debug_errno(errno, "Failed to describe key id %d: %m", serial);
|
||||
|
||||
if ((size_t) c <= sz)
|
||||
break;
|
||||
|
||||
sz = c;
|
||||
free(tuple);
|
||||
}
|
||||
|
||||
/* The kernel returns a final NUL in the string, verify that. */
|
||||
assert(tuple[c-1] == 0);
|
||||
|
||||
*ret = TAKE_PTR(tuple);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -9,3 +9,4 @@
|
|||
#define TAKE_KEY_SERIAL(key_serial) TAKE_GENERIC(key_serial, key_serial_t, -1)
|
||||
|
||||
int keyring_read(key_serial_t serial, void **ret, size_t *ret_size);
|
||||
int keyring_describe(key_serial_t serial, char **ret);
|
|
@ -57,6 +57,7 @@ basic_sources = files(
|
|||
'lock-util.c',
|
||||
'log.c',
|
||||
'login-util.c',
|
||||
'keyring-util.c',
|
||||
'memfd-util.c',
|
||||
'memory-util.c',
|
||||
'mempool.c',
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "homework-fscrypt.h"
|
||||
#include "homework-mount.h"
|
||||
#include "homework-quota.h"
|
||||
#include "keyring-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_keyctl.h"
|
||||
#include "missing_syscall.h"
|
||||
|
@ -29,6 +30,98 @@
|
|||
#include "user-util.h"
|
||||
#include "xattr-util.h"
|
||||
|
||||
static int fscrypt_unlink_key(UserRecord *h) {
|
||||
_cleanup_free_ void *keyring = NULL;
|
||||
size_t keyring_size = 0, n_keys = 0;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
assert(user_record_storage(h) == USER_FSCRYPT);
|
||||
|
||||
r = fully_set_uid_gid(
|
||||
h->uid,
|
||||
user_record_gid(h),
|
||||
/* supplementary_gids= */ NULL,
|
||||
/* n_supplementary_gids= */ 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change UID/GID to " UID_FMT "/" GID_FMT ": %m",
|
||||
h->uid, user_record_gid(h));
|
||||
|
||||
r = keyring_read(KEY_SPEC_USER_KEYRING, &keyring, &keyring_size);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read the keyring of user " UID_FMT ": %m", h->uid);
|
||||
|
||||
n_keys = keyring_size / sizeof(key_serial_t);
|
||||
assert(keyring_size % sizeof(key_serial_t) == 0);
|
||||
|
||||
/* Find any key with a description starting with 'fscrypt:' and unlink it. We need to iterate as we
|
||||
* store the key with a description that uses the hash of the secret key, that we do not have when
|
||||
* we are deactivating. */
|
||||
FOREACH_ARRAY(key, ((key_serial_t *) keyring), n_keys) {
|
||||
_cleanup_free_ char *description = NULL;
|
||||
char *d;
|
||||
|
||||
r = keyring_describe(*key, &description);
|
||||
if (r < 0) {
|
||||
if (r == -ENOKEY) /* Something else deleted it already, that's ok. */
|
||||
continue;
|
||||
|
||||
return log_error_errno(r, "Failed to describe key id %d: %m", *key);
|
||||
}
|
||||
|
||||
/* The decription is the final element as per manpage. */
|
||||
d = strrchr(description, ';');
|
||||
if (!d)
|
||||
return log_error_errno(
|
||||
SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to parse description of key id %d: %s",
|
||||
*key,
|
||||
description);
|
||||
|
||||
if (!startswith(d + 1, "fscrypt:"))
|
||||
continue;
|
||||
|
||||
r = keyctl(KEYCTL_UNLINK, *key, KEY_SPEC_USER_KEYRING, 0, 0);
|
||||
if (r < 0) {
|
||||
if (errno == ENOKEY) /* Something else deleted it already, that's ok. */
|
||||
continue;
|
||||
|
||||
return log_error_errno(
|
||||
errno,
|
||||
"Failed to delete encryption key with id '%d' from the keyring of user " UID_FMT ": %m",
|
||||
*key,
|
||||
h->uid);
|
||||
}
|
||||
|
||||
log_debug("Deleted encryption key with id '%d' from the keyring of user " UID_FMT ".", *key, h->uid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int home_flush_keyring_fscrypt(UserRecord *h) {
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
assert(user_record_storage(h) == USER_FSCRYPT);
|
||||
|
||||
if (!uid_is_valid(h->uid))
|
||||
return 0;
|
||||
|
||||
r = safe_fork("(sd-delkey)",
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
if (fscrypt_unlink_key(h) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fscrypt_upload_volume_key(
|
||||
const uint8_t key_descriptor[static FS_KEY_DESCRIPTOR_SIZE],
|
||||
const void *volume_key,
|
||||
|
|
|
@ -9,3 +9,5 @@ int home_setup_fscrypt(UserRecord *h, HomeSetup *setup, const PasswordCache *cac
|
|||
int home_create_fscrypt(UserRecord *h, HomeSetup *setup, char **effective_passwords, UserRecord **ret_home);
|
||||
|
||||
int home_passwd_fscrypt(UserRecord *h, HomeSetup *setup, const PasswordCache *cache, char **effective_passwords);
|
||||
|
||||
int home_flush_keyring_fscrypt(UserRecord *h);
|
||||
|
|
|
@ -379,6 +379,9 @@ static int keyring_flush(UserRecord *h) {
|
|||
|
||||
assert(h);
|
||||
|
||||
if (user_record_storage(h) == USER_FSCRYPT)
|
||||
(void) home_flush_keyring_fscrypt(h);
|
||||
|
||||
name = strjoin("homework-user-", h->user_name);
|
||||
if (!name)
|
||||
return log_oom();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "hmac.h"
|
||||
#include "id128-util.h"
|
||||
#include "io-util.h"
|
||||
#include "keyring-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "missing_threads.h"
|
||||
|
@ -202,7 +203,6 @@ static int get_invocation_from_keyring(sd_id128_t *ret) {
|
|||
char *d, *p, *g, *u, *e;
|
||||
unsigned long perms;
|
||||
key_serial_t key;
|
||||
size_t sz = 256;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
int r, c;
|
||||
|
@ -221,24 +221,9 @@ static int get_invocation_from_keyring(sd_id128_t *ret) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
description = new(char, sz);
|
||||
if (!description)
|
||||
return -ENOMEM;
|
||||
|
||||
c = keyctl(KEYCTL_DESCRIBE, key, (unsigned long) description, sz, 0);
|
||||
if (c < 0)
|
||||
return -errno;
|
||||
|
||||
if ((size_t) c <= sz)
|
||||
break;
|
||||
|
||||
sz = c;
|
||||
free(description);
|
||||
}
|
||||
|
||||
/* The kernel returns a final NUL in the string, verify that. */
|
||||
assert(description[c-1] == 0);
|
||||
r = keyring_describe(key, &description);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Chop off the final description string */
|
||||
d = strrchr(description, ';');
|
||||
|
|
|
@ -100,7 +100,6 @@ shared_sources = files(
|
|||
'kbd-util.c',
|
||||
'kernel-config.c',
|
||||
'kernel-image.c',
|
||||
'keyring-util.c',
|
||||
'killall.c',
|
||||
'label-util.c',
|
||||
'libarchive-util.c',
|
||||
|
|
Loading…
Reference in a new issue