From 677e6e679b56fe3f868d5f6175de28b7fab86474 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 14 Feb 2024 08:48:03 +0000 Subject: [PATCH] programs: sandbox {s,}waylock lockscreen --- hosts/common/programs/assorted.nix | 10 +++++++++- hosts/common/programs/waylock.nix | 10 +++++++++- hosts/common/users/default.nix | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/hosts/common/programs/assorted.nix b/hosts/common/programs/assorted.nix index 694c846a..930687a0 100644 --- a/hosts/common/programs/assorted.nix +++ b/hosts/common/programs/assorted.nix @@ -447,8 +447,16 @@ in superTux.sandbox.whitelistWayland = true; superTux.persist.byStore.plaintext = [ ".local/share/supertux2" ]; - swaylock.sandbox.method = "capshonly"; #< neither landlock nor bwrap works. pam_authenticate failed: invalid credentials. does it rely on SUID? + swaylock.sandbox.method = "bwrap"; swaylock.sandbox.wrapperType = "wrappedDerivation"; + swaylock.sandbox.extraPaths = [ + # N.B.: we need to be able to follow /etc/shadow to wherever it's symlinked. + # swaylock seems (?) to offload password checking to pam's `unix_chkpwd`, + # which needs read access to /etc/shadow. that can be either via suid bit (default; incompatible with sandbox) + # or by making /etc/shadow readable by the user (which is what i do -- check the activationScript) + "/etc/shadow" + ]; + swaylock.sandbox.whitelistWayland = true; tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ]; diff --git a/hosts/common/programs/waylock.nix b/hosts/common/programs/waylock.nix index e28d8865..200da3c7 100644 --- a/hosts/common/programs/waylock.nix +++ b/hosts/common/programs/waylock.nix @@ -6,8 +6,16 @@ let in { sane.programs.waylock = { - sandbox.method = "capshonly"; # not even landlock with full access to / works. + sandbox.method = "bwrap"; sandbox.wrapperType = "wrappedDerivation"; + sandbox.extraPaths = [ + # N.B.: we need to be able to follow /etc/shadow to wherever it's symlinked. + # waylock seems (?) to offload password checking to pam's `unix_chkpwd`, + # which needs read access to /etc/shadow. that can be either via suid bit (default; incompatible with sandbox) + # or by making /etc/shadow readable by the user (which is what i do -- check the activationScript) + "/etc/shadow" + ]; + sandbox.whitelistWayland = true; }; # without a /etc/pam.d/waylock entry, you may lock but you may never *unlock* ;-) diff --git a/hosts/common/users/default.nix b/hosts/common/users/default.nix index 152802c6..73ea82b9 100644 --- a/hosts/common/users/default.nix +++ b/hosts/common/users/default.nix @@ -33,6 +33,23 @@ in security.pam.mount.enable = true; + system.activationScripts.makeEtcShadowSandboxable = { + deps = [ "users" ]; + text = '' + # /etc is a public config directory. secrets like /etc/shadow don't belong there. + # move /etc/shadow to a non-config directory but link to it from /etc. + # this lets me keep all of /etc public, but only expose the private shadow file to sandboxed programs selectively. + # this is technically racy, but the nixos `users` activation script is not easily patchable. + mkdir -p /var/lib/etc_secrets + cp --preserve=all --dereference /etc/shadow /var/lib/etc_secrets/shadow + chown root:wheel /var/lib/etc_secrets/shadow + ln -sf /var/lib/etc_secrets/shadow /etc/shadow + ''; + }; + # define this specifically so that other parts of the config can know the real location of /etc/shadow + # i.e. so that sandboxed programs which require it can indeed provision it (sane.programs.sandbox...) + sane.fs."/etc/shadow".symlink.target = "/var/lib/etc_secrets/shadow"; + # pam.d ordering (auth section only): # /etc/pam.d/greetd: # auth optional pam_unix.so likeauth nullok # unix-early (order 11600)