`mkfs` when formatting LUKS home directories. There's one variable for each
of the supported file systems for the LUKS home directory backend.
+* `$SYSTEMD_HOME_LOCK_FREEZE_SESSION` - Takes a boolean. When false, the user's
+ session will not be frozen when the home directory is locked. Note that the kernel
+ may still freeze any task that tries to access data from the user's locked home
+ directory. This can lead to data loss, security leaks, or other undesired behavior
+ caused by parts of the session becoming unresponsive due to disk I/O while other
+ parts of the session continue running. Thus, we highly recommend that this variable
+ isn't used unless necessary. Defaults to true.
+
`kernel-install`:
* `$KERNEL_INSTALL_BYPASS` – If set to "1", execution of kernel-install is skipped
#include <sys/mount.h>
#include "blockdev-util.h"
+#include "bus-unit-util.h"
#include "chown-recursive.h"
#include "copy.h"
+#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "filesystems.h"
+#include "format-util.h"
#include "fs-util.h"
#include "home-util.h"
#include "homework-blob.h"
return 1;
}
+static int user_session_freezer(uid_t uid, bool freeze_now, UnitFreezer *ret) {
+ _cleanup_free_ char *unit = NULL;
+ int r;
+
+ r = getenv_bool("SYSTEMD_HOME_LOCK_FREEZE_SESSION");
+ if (r < 0 && r != -ENXIO)
+ log_warning_errno(r, "Cannot parse value of $SYSTEMD_HOME_LOCK_FREEZE_SESSION, ignoring.");
+ else if (r == 0) {
+ if (freeze_now)
+ log_notice("Session remains unfrozen on explicit request ($SYSTEMD_HOME_LOCK_FREEZE_SESSION "
+ "is set to false). This is not recommended, and might result in unexpected behavior "
+ "including data loss!");
+ *ret = (UnitFreezer) {};
+ return 0;
+ }
+
+ if (asprintf(&unit, "user-" UID_FMT ".slice", uid) < 0)
+ return log_oom();
+
+ if (freeze_now)
+ r = unit_freezer_new_freeze(unit, ret);
+ else
+ r = unit_freezer_new(unit, ret);
+ if (r < 0)
+ return r;
+ return 1;
+}
+
static int home_lock(UserRecord *h) {
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
+ _cleanup_(unit_freezer_done_thaw) UnitFreezer freezer = {};
int r;
assert(h);
if (r != USER_TEST_MOUNTED)
return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home directory of %s is not mounted, can't lock.", h->user_name);
+ r = user_session_freezer(h->uid, /* freeze_now= */ true, &freezer);
+ if (r < 0)
+ log_warning_errno(r, "Failed to freeze user session, ignoring: %m");
+ else if (r == 0)
+ log_info("User session freeze disabled, skipping.");
+ else
+ log_info("Froze user session.");
+
r = home_lock_luks(h, &setup);
if (r < 0)
return r;
+ unit_freezer_done(&freezer); /* Don't thaw the user session. */
+
log_info("Everything completed.");
return 1;
}
static int home_unlock(UserRecord *h) {
_cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT;
+ _cleanup_(unit_freezer_done_thaw) UnitFreezer freezer = {};
_cleanup_(password_cache_free) PasswordCache cache = {};
int r;
if (r < 0)
return r;
+ /* We want to thaw the session only after it's safe to access $HOME */
+ r = user_session_freezer(h->uid, /* freeze_now= */ false, &freezer);
+ if (r < 0)
+ log_warning_errno(r, "Failed to recover freezer for user session, ignoring: %m");
+
log_info("Everything completed.");
return 1;
}