1
0
mirror of https://github.com/systemd/systemd synced 2026-03-31 04:04:54 +02:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Yu Watanabe
0522729e19 tree-wide: use AF_NETLINK instead of PF_NETLINK 2021-10-18 22:46:37 +02:00
Lennart Poettering
ec3f41e09c
Merge pull request #21034 from poettering/homed-password-cache-tweaks
homed: minor tweaks to the PasswordCache logic
2021-10-18 22:46:16 +02:00
Lennart Poettering
be0398bd4b
Merge pull request #21028 from poettering/watchdog-fixlets
pid1: various small watchdog tweaks and fixes
2021-10-18 22:45:44 +02:00
Lennart Poettering
a74e2e447f homework: move allocation/destruction into outer/generic scope
Previously in most cases we'd allocate the HomeSetup context object
in generic code in homework.c. But for some cases we allocated them
instead inside the specific code in homework-{cifs,directory,luks}.c
Let's clean that up, and systematically allocate it in the outer
"entrypoint" calls in homework.c instead of the inner ones.

This doesn't change much in behaviour (i.e. it just means when something
fails we'll now clean it up one stack frame further up). But it will
allow is to more easily work with the context objects, since we'll have
them around in all stack frames.
2021-10-18 22:45:19 +02:00
Lennart Poettering
4e660eca45 homework: unify code that opens the backing image file in open_image_file()
Also, reuse an already opened image file if we have one.
2021-10-18 22:41:34 +02:00
Lennart Poettering
3361d1ca1b homework: mae sure PasswordCache is really optional
It was supposed to be optional (i.e. there's a reason why we never
assert()ed on it), and in many codepaths it is, let's make sure it is
everywhere.
2021-10-18 15:35:41 +02:00
Lennart Poettering
37a1bf7f76 homework: make PasswordCache const wherever we can 2021-10-18 15:34:32 +02:00
Lennart Poettering
d9752ca196 watchdog: fix fd validity check 2021-10-18 11:27:39 +02:00
Lennart Poettering
ef52fa5bd1 watchdog: drop unnecessary variable 2021-10-18 11:27:39 +02:00
Lennart Poettering
59bcac0b1a watchdog: always prefer /dev/watchdog0 over /dev/watchdog 2021-10-18 11:27:39 +02:00
Lennart Poettering
a73b7b1b0e watchdog: fix error code handling 2021-10-18 11:27:39 +02:00
15 changed files with 166 additions and 98 deletions

View File

@ -144,7 +144,7 @@
depending on hardware capabilities).</para> depending on hardware capabilities).</para>
<para>If <varname>RuntimeWatchdogSec=</varname> is set to a non-zero value, the watchdog hardware <para>If <varname>RuntimeWatchdogSec=</varname> is set to a non-zero value, the watchdog hardware
(<filename>/dev/watchdog</filename> or the path specified with <varname>WatchdogDevice=</varname> or (<filename>/dev/watchdog0</filename> or the path specified with <varname>WatchdogDevice=</varname> or
the kernel option <varname>systemd.watchdog-device=</varname>) will be programmed to automatically the kernel option <varname>systemd.watchdog-device=</varname>) will be programmed to automatically
reboot the system if it is not contacted within the specified timeout interval. The system manager reboot the system if it is not contacted within the specified timeout interval. The system manager
will ensure to contact it at least once in half the specified timeout interval. This feature requires will ensure to contact it at least once in half the specified timeout interval. This feature requires
@ -182,7 +182,7 @@
<listitem><para>Configure the hardware watchdog device that the <listitem><para>Configure the hardware watchdog device that the
runtime and shutdown watchdog timers will open and use. Defaults runtime and shutdown watchdog timers will open and use. Defaults
to <filename>/dev/watchdog</filename>. This setting has no to <filename>/dev/watchdog0</filename>. This setting has no
effect if a hardware watchdog is not available.</para></listitem> effect if a hardware watchdog is not available.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -99,16 +99,17 @@ int home_setup_cifs(
int home_activate_cifs( int home_activate_cifs(
UserRecord *h, UserRecord *h,
HomeSetup *setup,
PasswordCache *cache, PasswordCache *cache,
UserRecord **ret_home) { UserRecord **ret_home) {
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
const char *hdo, *hd; const char *hdo, *hd;
int r; int r;
assert(h); assert(h);
assert(user_record_storage(h) == USER_CIFS); assert(user_record_storage(h) == USER_CIFS);
assert(setup);
assert(ret_home); assert(ret_home);
if (!h->cifs_service) if (!h->cifs_service)
@ -117,21 +118,21 @@ int home_activate_cifs(
assert_se(hdo = user_record_home_directory(h)); assert_se(hdo = user_record_home_directory(h));
hd = strdupa_safe(hdo); /* copy the string out, since it might change later in the home record object */ hd = strdupa_safe(hdo); /* copy the string out, since it might change later in the home record object */
r = home_setup_cifs(h, 0, &setup); r = home_setup_cifs(h, 0, setup);
if (r < 0) if (r < 0)
return r; return r;
r = home_refresh(h, &setup, NULL, cache, NULL, &new_home); r = home_refresh(h, setup, NULL, cache, NULL, &new_home);
if (r < 0) if (r < 0)
return r; return r;
setup.root_fd = safe_close(setup.root_fd); setup->root_fd = safe_close(setup->root_fd);
r = home_move_mount(NULL, hd); r = home_move_mount(NULL, hd);
if (r < 0) if (r < 0)
return r; return r;
setup.undo_mount = false; setup->undo_mount = false;
log_info("Everything completed."); log_info("Everything completed.");
@ -139,8 +140,7 @@ int home_activate_cifs(
return 1; return 1;
} }
int home_create_cifs(UserRecord *h, UserRecord **ret_home) { int home_create_cifs(UserRecord *h, HomeSetup *setup, UserRecord **ret_home) {
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
_cleanup_(closedirp) DIR *d = NULL; _cleanup_(closedirp) DIR *d = NULL;
_cleanup_close_ int copy = -1; _cleanup_close_ int copy = -1;
@ -148,6 +148,7 @@ int home_create_cifs(UserRecord *h, UserRecord **ret_home) {
assert(h); assert(h);
assert(user_record_storage(h) == USER_CIFS); assert(user_record_storage(h) == USER_CIFS);
assert(setup);
assert(ret_home); assert(ret_home);
if (!h->cifs_service) if (!h->cifs_service)
@ -160,11 +161,11 @@ int home_create_cifs(UserRecord *h, UserRecord **ret_home) {
return log_error_errno(errno, "Unable to detect whether /sbin/mount.cifs exists: %m"); return log_error_errno(errno, "Unable to detect whether /sbin/mount.cifs exists: %m");
} }
r = home_setup_cifs(h, 0, &setup); r = home_setup_cifs(h, 0, setup);
if (r < 0) if (r < 0)
return r; return r;
copy = fcntl(setup.root_fd, F_DUPFD_CLOEXEC, 3); copy = fcntl(setup->root_fd, F_DUPFD_CLOEXEC, 3);
if (copy < 0) if (copy < 0)
return -errno; return -errno;
@ -178,11 +179,11 @@ int home_create_cifs(UserRecord *h, UserRecord **ret_home) {
if (errno != 0) if (errno != 0)
return log_error_errno(errno, "Failed to detect if CIFS directory is empty: %m"); return log_error_errno(errno, "Failed to detect if CIFS directory is empty: %m");
r = home_populate(h, setup.root_fd); r = home_populate(h, setup->root_fd);
if (r < 0) if (r < 0)
return r; return r;
r = home_sync_and_statfs(setup.root_fd, NULL); r = home_sync_and_statfs(setup->root_fd, NULL);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -6,6 +6,6 @@
int home_setup_cifs(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup); int home_setup_cifs(UserRecord *h, HomeSetupFlags flags, HomeSetup *setup);
int home_activate_cifs(UserRecord *h, PasswordCache *cache, UserRecord **ret_home); int home_activate_cifs(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home);
int home_create_cifs(UserRecord *h, UserRecord **ret_home); int home_create_cifs(UserRecord *h, HomeSetup *setup, UserRecord **ret_home);

View File

@ -26,16 +26,17 @@ int home_setup_directory(UserRecord *h, HomeSetup *setup) {
int home_activate_directory( int home_activate_directory(
UserRecord *h, UserRecord *h,
HomeSetup *setup,
PasswordCache *cache, PasswordCache *cache,
UserRecord **ret_home) { UserRecord **ret_home) {
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *header_home = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *header_home = NULL;
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
const char *hdo, *hd, *ipo, *ip; const char *hdo, *hd, *ipo, *ip;
int r; int r;
assert(h); assert(h);
assert(IN_SET(user_record_storage(h), USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT)); assert(IN_SET(user_record_storage(h), USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT));
assert(setup);
assert(ret_home); assert(ret_home);
assert_se(ipo = user_record_image_path(h)); assert_se(ipo = user_record_image_path(h));
@ -44,15 +45,15 @@ int home_activate_directory(
assert_se(hdo = user_record_home_directory(h)); assert_se(hdo = user_record_home_directory(h));
hd = strdupa_safe(hdo); hd = strdupa_safe(hdo);
r = home_setup(h, 0, cache, &setup, &header_home); r = home_setup(h, 0, cache, setup, &header_home);
if (r < 0) if (r < 0)
return r; return r;
r = home_refresh(h, &setup, header_home, cache, NULL, &new_home); r = home_refresh(h, setup, header_home, cache, NULL, &new_home);
if (r < 0) if (r < 0)
return r; return r;
setup.root_fd = safe_close(setup.root_fd); setup->root_fd = safe_close(setup->root_fd);
/* Create mount point to mount over if necessary */ /* Create mount point to mount over if necessary */
if (!path_equal(ip, hd)) if (!path_equal(ip, hd))

View File

@ -5,6 +5,6 @@
#include "user-record.h" #include "user-record.h"
int home_setup_directory(UserRecord *h, HomeSetup *setup); int home_setup_directory(UserRecord *h, HomeSetup *setup);
int home_activate_directory(UserRecord *h, PasswordCache *cache, UserRecord **ret_home); int home_activate_directory(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home);
int home_create_directory_or_subvolume(UserRecord *h, UserRecord **ret_home); int home_create_directory_or_subvolume(UserRecord *h, UserRecord **ret_home);
int home_resize_directory(UserRecord *h, HomeSetupFlags flags, PasswordCache *cache, HomeSetup *setup, UserRecord **ret_home); int home_resize_directory(UserRecord *h, HomeSetupFlags flags, PasswordCache *cache, HomeSetup *setup, UserRecord **ret_home);

View File

@ -280,7 +280,7 @@ static int fscrypt_setup(
int home_setup_fscrypt( int home_setup_fscrypt(
UserRecord *h, UserRecord *h,
PasswordCache *cache, const PasswordCache *cache,
HomeSetup *setup) { HomeSetup *setup) {
_cleanup_(erase_and_freep) void *volume_key = NULL; _cleanup_(erase_and_freep) void *volume_key = NULL;
@ -584,7 +584,7 @@ int home_create_fscrypt(
int home_passwd_fscrypt( int home_passwd_fscrypt(
UserRecord *h, UserRecord *h,
HomeSetup *setup, HomeSetup *setup,
PasswordCache *cache, /* the passwords acquired via PKCS#11/FIDO2 security tokens */ const PasswordCache *cache, /* the passwords acquired via PKCS#11/FIDO2 security tokens */
char **effective_passwords /* new passwords */) { char **effective_passwords /* new passwords */) {
_cleanup_(erase_and_freep) void *volume_key = NULL; _cleanup_(erase_and_freep) void *volume_key = NULL;

View File

@ -4,7 +4,7 @@
#include "homework.h" #include "homework.h"
#include "user-record.h" #include "user-record.h"
int home_setup_fscrypt(UserRecord *h, PasswordCache *cache, HomeSetup *setup); int home_setup_fscrypt(UserRecord *h, const PasswordCache *cache, HomeSetup *setup);
int home_create_fscrypt(UserRecord *h, char **effective_passwords, UserRecord **ret_home); int home_create_fscrypt(UserRecord *h, char **effective_passwords, UserRecord **ret_home);
int home_passwd_fscrypt(UserRecord *h, HomeSetup *setup, PasswordCache *cache, char **effective_passwords); int home_passwd_fscrypt(UserRecord *h, HomeSetup *setup, const PasswordCache *cache, char **effective_passwords);

View File

@ -349,7 +349,10 @@ static int luks_setup(
return log_oom(); return log_oom();
r = -ENOKEY; r = -ENOKEY;
FOREACH_POINTER(list, cache->pkcs11_passwords, cache->fido2_passwords, passwords) { FOREACH_POINTER(list,
cache ? cache->pkcs11_passwords : NULL,
cache ? cache->fido2_passwords : NULL,
passwords) {
r = luks_try_passwords(cd, list, vk, &vks); r = luks_try_passwords(cd, list, vk, &vks);
if (r != -ENOKEY) if (r != -ENOKEY)
break; break;
@ -384,7 +387,7 @@ static int luks_setup(
static int luks_open( static int luks_open(
const char *dm_name, const char *dm_name,
char **passwords, char **passwords,
PasswordCache *cache, const PasswordCache *cache,
struct crypt_device **ret, struct crypt_device **ret,
sd_id128_t *ret_found_uuid, sd_id128_t *ret_found_uuid,
void **ret_volume_key, void **ret_volume_key,
@ -435,7 +438,10 @@ static int luks_open(
return log_oom(); return log_oom();
r = -ENOKEY; r = -ENOKEY;
FOREACH_POINTER(list, cache->pkcs11_passwords, cache->fido2_passwords, passwords) { FOREACH_POINTER(list,
cache ? cache->pkcs11_passwords : NULL,
cache ? cache->fido2_passwords : NULL,
passwords) {
r = luks_try_passwords(cd, list, vk, &vks); r = luks_try_passwords(cd, list, vk, &vks);
if (r != -ENOKEY) if (r != -ENOKEY)
break; break;
@ -1098,6 +1104,39 @@ static int lock_image_fd(int image_fd, const char *ip) {
return 0; return 0;
} }
static int open_image_file(
UserRecord *h,
const char *force_image_path,
struct stat *ret_stat) {
_cleanup_close_ int image_fd = -1;
struct stat st;
const char *ip;
int r;
ip = force_image_path ?: user_record_image_path(h);
image_fd = open(ip, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
if (image_fd < 0)
return log_error_errno(errno, "Failed to open image file %s: %m", ip);
if (fstat(image_fd, &st) < 0)
return log_error_errno(errno, "Failed to fstat() image file: %m");
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
return log_error_errno(
S_ISDIR(st.st_mode) ? SYNTHETIC_ERRNO(EISDIR) : SYNTHETIC_ERRNO(EBADFD),
"Image file %s is not a regular file or block device: %m", ip);
r = lock_image_fd(image_fd, ip);
if (r < 0)
return r;
if (ret_stat)
*ret_stat = st;
return TAKE_FD(image_fd);
}
int home_setup_luks( int home_setup_luks(
UserRecord *h, UserRecord *h,
HomeSetupFlags flags, HomeSetupFlags flags,
@ -1111,12 +1150,12 @@ int home_setup_luks(
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL; _cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(erase_and_freep) void *volume_key = NULL; _cleanup_(erase_and_freep) void *volume_key = NULL;
_cleanup_close_ int root_fd = -1, image_fd = -1; _cleanup_close_ int opened_image_fd = -1, root_fd = -1;
bool dm_activated = false, mounted = false; bool dm_activated = false, mounted = false;
size_t volume_key_size = 0; size_t volume_key_size = 0;
bool marked_dirty = false; bool marked_dirty = false;
uint64_t offset, size; uint64_t offset, size;
int r; int r, image_fd = -1;
assert(h); assert(h);
assert(setup); assert(setup);
@ -1225,20 +1264,15 @@ int home_setup_luks(
if (!subdir) if (!subdir)
return log_oom(); return log_oom();
image_fd = open(ip, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); /* Reuse the image fd if it has already been opened by an earlier step */
if (image_fd < 0) if (setup->image_fd < 0) {
return log_error_errno(errno, "Failed to open image file %s: %m", ip); opened_image_fd = open_image_file(h, force_image_path, &st);
if (opened_image_fd < 0)
return opened_image_fd;
if (fstat(image_fd, &st) < 0) image_fd = opened_image_fd;
return log_error_errno(errno, "Failed to fstat() image file: %m"); } else
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode)) image_fd = setup->image_fd;
return log_error_errno(
S_ISDIR(st.st_mode) ? SYNTHETIC_ERRNO(EISDIR) : SYNTHETIC_ERRNO(EBADFD),
"Image file %s is not a regular file or block device: %m", ip);
r = lock_image_fd(image_fd, ip);
if (r < 0)
return r;
r = luks_validate(image_fd, user_record_user_name_and_realm(h), h->partition_uuid, &found_partition_uuid, &offset, &size); r = luks_validate(image_fd, user_record_user_name_and_realm(h), h->partition_uuid, &found_partition_uuid, &offset, &size);
if (r < 0) if (r < 0)
@ -1309,7 +1343,12 @@ int home_setup_luks(
if (user_record_luks_discard(h)) if (user_record_luks_discard(h))
(void) run_fitrim(root_fd); (void) run_fitrim(root_fd);
setup->image_fd = TAKE_FD(image_fd); /* And now, fill in everything */
if (opened_image_fd >= 0) {
safe_close(setup->image_fd);
setup->image_fd = TAKE_FD(opened_image_fd);
}
setup->do_offline_fallocate = !(setup->do_offline_fitrim = user_record_luks_offline_discard(h)); setup->do_offline_fallocate = !(setup->do_offline_fitrim = user_record_luks_offline_discard(h));
setup->do_mark_clean = marked_dirty; setup->do_mark_clean = marked_dirty;
} }
@ -1358,11 +1397,11 @@ static void print_size_summary(uint64_t host_size, uint64_t encrypted_size, stru
int home_activate_luks( int home_activate_luks(
UserRecord *h, UserRecord *h,
HomeSetup *setup,
PasswordCache *cache, PasswordCache *cache,
UserRecord **ret_home) { UserRecord **ret_home) {
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *luks_home_record = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL, *luks_home_record = NULL;
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
uint64_t host_size, encrypted_size; uint64_t host_size, encrypted_size;
const char *hdo, *hd; const char *hdo, *hd;
struct statfs sfs; struct statfs sfs;
@ -1370,6 +1409,7 @@ int home_activate_luks(
assert(h); assert(h);
assert(user_record_storage(h) == USER_LUKS); assert(user_record_storage(h) == USER_LUKS);
assert(setup);
assert(ret_home); assert(ret_home);
r = dlopen_cryptsetup(); r = dlopen_cryptsetup();
@ -1379,33 +1419,33 @@ int home_activate_luks(
assert_se(hdo = user_record_home_directory(h)); assert_se(hdo = user_record_home_directory(h));
hd = strdupa_safe(hdo); /* copy the string out, since it might change later in the home record object */ hd = strdupa_safe(hdo); /* copy the string out, since it might change later in the home record object */
r = home_get_state_luks(h, &setup); r = home_get_state_luks(h, setup);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0)
return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Device mapper device %s already exists, refusing.", setup.dm_node); return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Device mapper device %s already exists, refusing.", setup->dm_node);
r = home_setup_luks( r = home_setup_luks(
h, h,
0, 0,
NULL, NULL,
cache, cache,
&setup, setup,
&luks_home_record); &luks_home_record);
if (r < 0) if (r < 0)
return r; return r;
r = block_get_size_by_fd(setup.loop->fd, &host_size); r = block_get_size_by_fd(setup->loop->fd, &host_size);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to get loopback block device size: %m"); return log_error_errno(r, "Failed to get loopback block device size: %m");
r = block_get_size_by_path(setup.dm_node, &encrypted_size); r = block_get_size_by_path(setup->dm_node, &encrypted_size);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to get LUKS block device size: %m"); return log_error_errno(r, "Failed to get LUKS block device size: %m");
r = home_refresh( r = home_refresh(
h, h,
&setup, setup,
luks_home_record, luks_home_record,
cache, cache,
&sfs, &sfs,
@ -1413,28 +1453,28 @@ int home_activate_luks(
if (r < 0) if (r < 0)
return r; return r;
r = home_extend_embedded_identity(new_home, h, &setup); r = home_extend_embedded_identity(new_home, h, setup);
if (r < 0) if (r < 0)
return r; return r;
setup.root_fd = safe_close(setup.root_fd); setup->root_fd = safe_close(setup->root_fd);
r = home_move_mount(user_record_user_name_and_realm(h), hd); r = home_move_mount(user_record_user_name_and_realm(h), hd);
if (r < 0) if (r < 0)
return r; return r;
setup.undo_mount = false; setup->undo_mount = false;
setup.do_offline_fitrim = false; setup->do_offline_fitrim = false;
loop_device_relinquish(setup.loop); loop_device_relinquish(setup->loop);
r = sym_crypt_deactivate_by_name(NULL, setup.dm_name, CRYPT_DEACTIVATE_DEFERRED); r = sym_crypt_deactivate_by_name(NULL, setup->dm_name, CRYPT_DEACTIVATE_DEFERRED);
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to relinquish DM device, ignoring: %m"); log_warning_errno(r, "Failed to relinquish DM device, ignoring: %m");
setup.undo_dm = false; setup->undo_dm = false;
setup.do_offline_fallocate = false; setup->do_offline_fallocate = false;
setup.do_mark_clean = false; setup->do_mark_clean = false;
log_info("Everything completed."); log_info("Everything completed.");
@ -1614,8 +1654,7 @@ static int luks_format(
STRV_FOREACH(pp, effective_passwords) { STRV_FOREACH(pp, effective_passwords) {
if (strv_contains(cache->pkcs11_passwords, *pp) || if (password_cache_contains(cache, *pp)) { /* is this a fido2 or pkcs11 password? */
strv_contains(cache->fido2_passwords, *pp)) {
log_debug("Using minimal PBKDF for slot %i", slot); log_debug("Using minimal PBKDF for slot %i", slot);
r = sym_crypt_set_pbkdf_type(cd, &minimal_pbkdf); r = sym_crypt_set_pbkdf_type(cd, &minimal_pbkdf);
} else { } else {
@ -1952,7 +1991,7 @@ static int home_truncate(
int home_create_luks( int home_create_luks(
UserRecord *h, UserRecord *h,
PasswordCache *cache, const PasswordCache *cache,
char **effective_passwords, char **effective_passwords,
UserRecord **ret_home) { UserRecord **ret_home) {
@ -2709,13 +2748,13 @@ int home_resize_luks(
uint64_t old_image_size, new_image_size, old_fs_size, new_fs_size, crypto_offset, new_partition_size; uint64_t old_image_size, new_image_size, old_fs_size, new_fs_size, crypto_offset, new_partition_size;
_cleanup_(user_record_unrefp) UserRecord *header_home = NULL, *embedded_home = NULL, *new_home = NULL; _cleanup_(user_record_unrefp) UserRecord *header_home = NULL, *embedded_home = NULL, *new_home = NULL;
_cleanup_(fdisk_unref_tablep) struct fdisk_table *table = NULL; _cleanup_(fdisk_unref_tablep) struct fdisk_table *table = NULL;
_cleanup_close_ int opened_image_fd = -1;
_cleanup_free_ char *whole_disk = NULL; _cleanup_free_ char *whole_disk = NULL;
_cleanup_close_ int image_fd = -1; int r, resize_type, image_fd = -1;
sd_id128_t disk_uuid; sd_id128_t disk_uuid;
const char *ip, *ipo; const char *ip, *ipo;
struct statfs sfs; struct statfs sfs;
struct stat st; struct stat st;
int r, resize_type;
assert(h); assert(h);
assert(user_record_storage(h) == USER_LUKS); assert(user_record_storage(h) == USER_LUKS);
@ -2729,12 +2768,17 @@ int home_resize_luks(
assert_se(ipo = user_record_image_path(h)); assert_se(ipo = user_record_image_path(h));
ip = strdupa_safe(ipo); /* copy out since original might change later in home record object */ ip = strdupa_safe(ipo); /* copy out since original might change later in home record object */
image_fd = open(ip, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (setup->image_fd < 0) {
if (image_fd < 0) setup->image_fd = open_image_file(h, NULL, &st);
return log_error_errno(errno, "Failed to open image file %s: %m", ip); if (setup->image_fd < 0)
return setup->image_fd;
if (fstat(image_fd, &st) < 0) } else {
if (fstat(setup->image_fd, &st) < 0)
return log_error_errno(errno, "Failed to stat image file %s: %m", ip); return log_error_errno(errno, "Failed to stat image file %s: %m", ip);
}
image_fd = setup->image_fd;
if (S_ISBLK(st.st_mode)) { if (S_ISBLK(st.st_mode)) {
dev_t parent; dev_t parent;
@ -2752,12 +2796,12 @@ int home_resize_luks(
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to derive whole disk path for %s: %m", ip); return log_error_errno(r, "Failed to derive whole disk path for %s: %m", ip);
safe_close(image_fd); opened_image_fd = open(whole_disk, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
if (opened_image_fd < 0)
image_fd = open(whole_disk, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
if (image_fd < 0)
return log_error_errno(errno, "Failed to open whole block device %s: %m", whole_disk); return log_error_errno(errno, "Failed to open whole block device %s: %m", whole_disk);
image_fd = opened_image_fd;
if (fstat(image_fd, &st) < 0) if (fstat(image_fd, &st) < 0)
return log_error_errno(errno, "Failed to stat whole block device %s: %m", whole_disk); return log_error_errno(errno, "Failed to stat whole block device %s: %m", whole_disk);
if (!S_ISBLK(st.st_mode)) if (!S_ISBLK(st.st_mode))
@ -3014,7 +3058,7 @@ int home_resize_luks(
int home_passwd_luks( int home_passwd_luks(
UserRecord *h, UserRecord *h,
HomeSetup *setup, HomeSetup *setup,
PasswordCache *cache, /* the passwords acquired via PKCS#11/FIDO2 security tokens */ const PasswordCache *cache, /* the passwords acquired via PKCS#11/FIDO2 security tokens */
char **effective_passwords /* new passwords */) { char **effective_passwords /* new passwords */) {
size_t volume_key_size, max_key_slots, n_effective; size_t volume_key_size, max_key_slots, n_effective;
@ -3051,7 +3095,11 @@ int home_passwd_luks(
return log_oom(); return log_oom();
r = -ENOKEY; r = -ENOKEY;
FOREACH_POINTER(list, cache->pkcs11_passwords, cache->fido2_passwords, h->password) { FOREACH_POINTER(list,
cache ? cache->pkcs11_passwords : NULL,
cache ? cache->fido2_passwords : NULL,
h->password) {
r = luks_try_passwords(setup->crypt_device, list, volume_key, &volume_key_size); r = luks_try_passwords(setup->crypt_device, list, volume_key, &volume_key_size);
if (r != -ENOKEY) if (r != -ENOKEY)
break; break;
@ -3077,8 +3125,7 @@ int home_passwd_luks(
continue; continue;
} }
if (strv_contains(cache->pkcs11_passwords, effective_passwords[i]) || if (password_cache_contains(cache, effective_passwords[i])) { /* Is this a FIDO2 or PKCS#11 password? */
strv_contains(cache->fido2_passwords, effective_passwords[i])) {
log_debug("Using minimal PBKDF for slot %zu", i); log_debug("Using minimal PBKDF for slot %zu", i);
r = sym_crypt_set_pbkdf_type(setup->crypt_device, &minimal_pbkdf); r = sym_crypt_set_pbkdf_type(setup->crypt_device, &minimal_pbkdf);
} else { } else {
@ -3179,7 +3226,7 @@ static int luks_try_resume(
return -ENOKEY; return -ENOKEY;
} }
int home_unlock_luks(UserRecord *h, PasswordCache *cache) { int home_unlock_luks(UserRecord *h, const PasswordCache *cache) {
_cleanup_free_ char *dm_name = NULL, *dm_node = NULL; _cleanup_free_ char *dm_name = NULL, *dm_node = NULL;
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
char **list; char **list;
@ -3203,7 +3250,10 @@ int home_unlock_luks(UserRecord *h, PasswordCache *cache) {
cryptsetup_enable_logging(cd); cryptsetup_enable_logging(cd);
r = -ENOKEY; r = -ENOKEY;
FOREACH_POINTER(list, cache->pkcs11_passwords, cache->fido2_passwords, h->password) { FOREACH_POINTER(list,
cache ? cache->pkcs11_passwords : NULL,
cache ? cache->fido2_passwords : NULL,
h->password) {
r = luks_try_resume(cd, dm_name, list); r = luks_try_resume(cd, dm_name, list);
if (r != -ENOKEY) if (r != -ENOKEY)
break; break;

View File

@ -7,22 +7,22 @@
int home_setup_luks(UserRecord *h, HomeSetupFlags flags, const char *force_image_path, PasswordCache *cache, HomeSetup *setup, UserRecord **ret_luks_home); int home_setup_luks(UserRecord *h, HomeSetupFlags flags, const char *force_image_path, PasswordCache *cache, HomeSetup *setup, UserRecord **ret_luks_home);
int home_activate_luks(UserRecord *h, PasswordCache *cache, UserRecord **ret_home); int home_activate_luks(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home);
int home_deactivate_luks(UserRecord *h); int home_deactivate_luks(UserRecord *h);
int home_trim_luks(UserRecord *h); int home_trim_luks(UserRecord *h);
int home_store_header_identity_luks(UserRecord *h, HomeSetup *setup, UserRecord *old_home); int home_store_header_identity_luks(UserRecord *h, HomeSetup *setup, UserRecord *old_home);
int home_create_luks(UserRecord *h, PasswordCache *cache, char **effective_passwords, UserRecord **ret_home); int home_create_luks(UserRecord *h, const PasswordCache *cache, char **effective_passwords, UserRecord **ret_home);
int home_get_state_luks(UserRecord *h, HomeSetup *setup); int home_get_state_luks(UserRecord *h, HomeSetup *setup);
int home_resize_luks(UserRecord *h, HomeSetupFlags flags, PasswordCache *cache, HomeSetup *setup, UserRecord **ret_home); int home_resize_luks(UserRecord *h, HomeSetupFlags flags, PasswordCache *cache, HomeSetup *setup, UserRecord **ret_home);
int home_passwd_luks(UserRecord *h, HomeSetup *setup, PasswordCache *cache, char **effective_passwords); int home_passwd_luks(UserRecord *h, HomeSetup *setup, const PasswordCache *cache, char **effective_passwords);
int home_lock_luks(UserRecord *h); int home_lock_luks(UserRecord *h);
int home_unlock_luks(UserRecord *h, PasswordCache *cache); int home_unlock_luks(UserRecord *h, const PasswordCache *cache);
static inline uint64_t luks_volume_key_size_convert(struct crypt_device *cd) { static inline uint64_t luks_volume_key_size_convert(struct crypt_device *cd) {
int k; int k;

View File

@ -759,8 +759,9 @@ int home_refresh(
} }
static int home_activate(UserRecord *h, UserRecord **ret_home) { static int home_activate(UserRecord *h, UserRecord **ret_home) {
_cleanup_(password_cache_free) PasswordCache cache = {}; _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
_cleanup_(password_cache_free) PasswordCache cache = {};
int r; int r;
assert(h); assert(h);
@ -791,7 +792,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) {
switch (user_record_storage(h)) { switch (user_record_storage(h)) {
case USER_LUKS: case USER_LUKS:
r = home_activate_luks(h, &cache, &new_home); r = home_activate_luks(h, &setup, &cache, &new_home);
if (r < 0) if (r < 0)
return r; return r;
@ -800,14 +801,14 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) {
case USER_SUBVOLUME: case USER_SUBVOLUME:
case USER_DIRECTORY: case USER_DIRECTORY:
case USER_FSCRYPT: case USER_FSCRYPT:
r = home_activate_directory(h, &cache, &new_home); r = home_activate_directory(h, &setup, &cache, &new_home);
if (r < 0) if (r < 0)
return r; return r;
break; break;
case USER_CIFS: case USER_CIFS:
r = home_activate_cifs(h, &cache, &new_home); r = home_activate_cifs(h, &setup, &cache, &new_home);
if (r < 0) if (r < 0)
return r; return r;
@ -1163,6 +1164,7 @@ static int determine_default_storage(UserStorage *ret) {
static int home_create(UserRecord *h, UserRecord **ret_home) { static int home_create(UserRecord *h, UserRecord **ret_home) {
_cleanup_(strv_free_erasep) char **effective_passwords = NULL; _cleanup_(strv_free_erasep) char **effective_passwords = NULL;
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
_cleanup_(user_record_unrefp) UserRecord *new_home = NULL; _cleanup_(user_record_unrefp) UserRecord *new_home = NULL;
_cleanup_(password_cache_free) PasswordCache cache = {}; _cleanup_(password_cache_free) PasswordCache cache = {};
UserStorage new_storage = _USER_STORAGE_INVALID; UserStorage new_storage = _USER_STORAGE_INVALID;
@ -1238,7 +1240,7 @@ static int home_create(UserRecord *h, UserRecord **ret_home) {
break; break;
case USER_CIFS: case USER_CIFS:
r = home_create_cifs(h, &new_home); r = home_create_cifs(h, &setup, &new_home);
break; break;
default: default:

View File

@ -7,6 +7,7 @@
#include "sd-id128.h" #include "sd-id128.h"
#include "loop-util.h" #include "loop-util.h"
#include "strv.h"
#include "user-record.h" #include "user-record.h"
#include "user-record-util.h" #include "user-record-util.h"
@ -39,13 +40,21 @@ typedef struct HomeSetup {
} HomeSetup; } HomeSetup;
typedef struct PasswordCache { typedef struct PasswordCache {
/* Decoding passwords from security tokens is expensive and typically requires user interaction, hence cache any we already figured out. */ /* Decoding passwords from security tokens is expensive and typically requires user interaction,
* hence cache any we already figured out. */
char **pkcs11_passwords; char **pkcs11_passwords;
char **fido2_passwords; char **fido2_passwords;
} PasswordCache; } PasswordCache;
void password_cache_free(PasswordCache *cache); void password_cache_free(PasswordCache *cache);
static inline bool password_cache_contains(const PasswordCache *cache, const char *p) {
if (!cache)
return false;
return strv_contains(cache->pkcs11_passwords, p) || strv_contains(cache->fido2_passwords, p);
}
#define HOME_SETUP_INIT \ #define HOME_SETUP_INIT \
{ \ { \
.root_fd = -1, \ .root_fd = -1, \

View File

@ -143,7 +143,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
} }
if (fd < 0) { if (fd < 0) {
sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); sock = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
if (sock < 0) if (sock < 0)
return log_debug_errno(errno, "sd-device-monitor: Failed to create socket: %m"); return log_debug_errno(errno, "sd-device-monitor: Failed to create socket: %m");
} }

View File

@ -20,7 +20,7 @@
int socket_open(int family) { int socket_open(int family) {
int fd; int fd;
fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, family); fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, family);
if (fd < 0) if (fd < 0)
return -errno; return -errno;

View File

@ -174,7 +174,7 @@ int expose_port_send_rtnl(int send_fd) {
assert(send_fd >= 0); assert(send_fd >= 0);
fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE); fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE);
if (fd < 0) if (fd < 0)
return log_error_errno(errno, "Failed to allocate container netlink: %m"); return log_error_errno(errno, "Failed to allocate container netlink: %m");

View File

@ -10,6 +10,7 @@
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "log.h" #include "log.h"
#include "path-util.h"
#include "string-util.h" #include "string-util.h"
#include "time-util.h" #include "time-util.h"
#include "watchdog.h" #include "watchdog.h"
@ -21,12 +22,10 @@ static usec_t watchdog_last_ping = USEC_INFINITY;
static int watchdog_set_enable(bool enable) { static int watchdog_set_enable(bool enable) {
int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD; int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD;
int r;
assert(watchdog_fd >= 0); assert(watchdog_fd >= 0);
r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0) {
if (r < 0) {
if (!enable) if (!enable)
return log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m"); return log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
@ -43,7 +42,7 @@ static int watchdog_set_enable(bool enable) {
static int watchdog_get_timeout(void) { static int watchdog_get_timeout(void) {
int sec = 0; int sec = 0;
assert(watchdog_fd > 0); assert(watchdog_fd >= 0);
if (ioctl(watchdog_fd, WDIOC_GETTIMEOUT, &sec) < 0) if (ioctl(watchdog_fd, WDIOC_GETTIMEOUT, &sec) < 0)
return -errno; return -errno;
@ -107,7 +106,7 @@ static int update_timeout(void) {
if (watchdog_timeout == USEC_INFINITY) { if (watchdog_timeout == USEC_INFINITY) {
r = watchdog_get_timeout(); r = watchdog_get_timeout();
if (r < 0) if (r < 0)
return log_error_errno(errno, "Failed to query watchdog HW timeout: %m"); return log_error_errno(r, "Failed to query watchdog HW timeout: %m");
} }
r = watchdog_set_enable(true); r = watchdog_set_enable(true);
@ -127,7 +126,13 @@ static int open_watchdog(void) {
if (watchdog_fd >= 0) if (watchdog_fd >= 0)
return 0; return 0;
fn = watchdog_device ?: "/dev/watchdog"; /* Let's prefer new-style /dev/watchdog0 (i.e. kernel 3.5+) over classic /dev/watchdog. The former
* has the benefit that we can easily find the matching directory in sysfs from it, as the relevant
* sysfs attributes can only be found via /sys/dev/char/<major>:<minor> if the new-style device
* major/minor is used, not the old-style. */
fn = !watchdog_device || path_equal(watchdog_device, "/dev/watchdog") ?
"/dev/watchdog0" : watchdog_device;
watchdog_fd = open(fn, O_WRONLY|O_CLOEXEC); watchdog_fd = open(fn, O_WRONLY|O_CLOEXEC);
if (watchdog_fd < 0) if (watchdog_fd < 0)
return log_debug_errno(errno, "Failed to open watchdog device %s, ignoring: %m", fn); return log_debug_errno(errno, "Failed to open watchdog device %s, ignoring: %m", fn);