systemd: rework emergency/rescue targets to be safer

This commit is contained in:
2025-05-30 01:14:11 +00:00
parent 82096288e2
commit 92f68baaf9
4 changed files with 38 additions and 3 deletions

View File

@@ -24,9 +24,20 @@ let
type = fsType; type = fsType;
options = lib.concatStringsSep "," options; options = lib.concatStringsSep "," options;
wantedBy = [ "default.target" ]; wantedBy = [ "default.target" ];
after = [ "network-online.target" ]; after = [
"emergency.service"
"network-online.target"
];
requires = [ "network-online.target" ]; requires = [ "network-online.target" ];
unitConfig.Conflicts = [
# emergency.service drops the user into a root shell;
# only accessible via physical TTY, but unmount sensitive data before that as a precaution.
"emergency.service"
];
# mountConfig.LazyUnmount = true; #< else it _ocassionally_ fails "target is busy"
mountConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ]; mountConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ];
mountConfig.User = "colin"; mountConfig.User = "colin";
mountConfig.AmbientCapabilities = "CAP_SETPCAP CAP_SYS_ADMIN"; mountConfig.AmbientCapabilities = "CAP_SETPCAP CAP_SYS_ADMIN";

View File

@@ -132,8 +132,12 @@ in
# fixes "Cannot open access to console, the root account is locked" on systemd init failure. # fixes "Cannot open access to console, the root account is locked" on systemd init failure.
# see: <https://github.com/systemd/systemd/commit/33eb44fe4a8d7971b5614bc4c2d90f8d91cce66c> # see: <https://github.com/systemd/systemd/commit/33eb44fe4a8d7971b5614bc4c2d90f8d91cce66c>
# - emergency: kill (or don't start) everything; drop into root shell.
# - rescue: start sysinit.target (which mounts the local-fs, and others), and drop into root shell.
# enable emergency.target; configure elsewhere everything sensitive (e.g. /mnt/persist/private) to conflict with it.
# because of `rescue.target`'s `Requires=sysinit.target`, we can't (easily) allow its root shell safely.
systemd.services.emergency.environment.SYSTEMD_SULOGIN_FORCE = "1"; systemd.services.emergency.environment.SYSTEMD_SULOGIN_FORCE = "1";
systemd.services.rescue.environment.SYSTEMD_SULOGIN_FORCE = "1"; # systemd.services.rescue.environment.SYSTEMD_SULOGIN_FORCE = "1";
# harden base systemd services # harden base systemd services
# see: `systemd-analyze security` # see: `systemd-analyze security`

View File

@@ -65,9 +65,20 @@ lib.mkIf config.sane.persist.enable
type = fsType; type = fsType;
options = lib.concatStringsSep "," options; options = lib.concatStringsSep "," options;
wantedBy = [ "local-fs.target" ]; wantedBy = [ "local-fs.target" ];
before = [ "local-fs.target" ]; before = [
"emergency.service"
"local-fs.target"
];
unitConfig.RequiresMountsFor = [ backing ]; unitConfig.RequiresMountsFor = [ backing ];
unitConfig.Conflicts = [
# emergency.service drops the user into a root shell;
# only accessible via physical TTY, but unmount sensitive data before that as a precaution.
"emergency.service"
];
mountConfig.LazyUnmount = true; #< else it usually fails "target is busy"
# hardening (systemd-analyze security mnt-persist-ephemeral.mount) # hardening (systemd-analyze security mnt-persist-ephemeral.mount)
mountConfig.AmbientCapabilities = "CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_CHOWN CAP_MKNOD CAP_LEASE CAP_SETGID CAP_SETUID CAP_FOWNER"; mountConfig.AmbientCapabilities = "CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_CHOWN CAP_MKNOD CAP_LEASE CAP_SETGID CAP_SETUID CAP_FOWNER";
# CAP_LEASE is probably not necessary -- does any fs user use leases? # CAP_LEASE is probably not necessary -- does any fs user use leases?

View File

@@ -92,12 +92,21 @@ lib.mkIf config.sane.persist.enable
type = fsType; type = fsType;
options = lib.concatStringsSep "," options; options = lib.concatStringsSep "," options;
after = [ "gocryptfs-private-key.service" ]; after = [ "gocryptfs-private-key.service" ];
before = [ "emergency.service" ];
wants = [ "gocryptfs-private-key.service" ]; wants = [ "gocryptfs-private-key.service" ];
unitConfig.Conflicts = [
# emergency.service drops the user into a root shell;
# only accessible via physical TTY, but unmount sensitive data before that as a precaution.
"emergency.service"
];
unitConfig.RequiresMountsFor = [ backing ]; unitConfig.RequiresMountsFor = [ backing ];
# unitConfig.DefaultDependencies = "no"; # unitConfig.DefaultDependencies = "no";
# mountConfig.TimeoutSec = "infinity"; # mountConfig.TimeoutSec = "infinity";
mountConfig.LazyUnmount = true; #< else it usually fails "target is busy"
# hardening (systemd-analyze security mnt-persist-private.mount) # hardening (systemd-analyze security mnt-persist-private.mount)
mountConfig.AmbientCapabilities = "CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_CHOWN CAP_MKNOD CAP_LEASE CAP_SETGID CAP_SETUID CAP_FOWNER"; mountConfig.AmbientCapabilities = "CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_CHOWN CAP_MKNOD CAP_LEASE CAP_SETGID CAP_SETUID CAP_FOWNER";
# CAP_LEASE is probably not necessary -- does any fs user use leases? # CAP_LEASE is probably not necessary -- does any fs user use leases?