Files
nixos-installer/modules/experiments/noexec.nix.md
Niklas Gollenstede a4ae2ab551 upgrade to 22.11, add extlinux & hetzner-vps:
- disable wip.fs.disks.devices.*.gptOffset (patch broken with 22.11),
- add wip.bootloader.extlinux,
- add wip.hardware.hetzner-vps profile,
- fix wip.services.dropbear.socketActivation,
2022-12-28 16:43:16 +01:00

75 lines
3.3 KiB
Markdown

/*
# `mount a -o noexec` Experiment
This is a (so far not successful) experiment to mount (almost) all filesystems as `noexec`, `nosuid` and `nodev` -- and to then deal with the consequences.
## Exceptions
* `/dev` and `/dev/pts` need `dev`
* `/run/wrappers` needs `exec` `suid`
* `/run/binfmt` needs `exec`
* `/run` `/run/user/*` may need `exec` (TODO: test)
* The Nix build dir (default: `/tmp`) needs `exec` (TODO!)
* Some parts of `/home/<user>/` will need `exec`
## Implementation
```nix
#*/# end of MarkDown, beginning of NixOS module:
dirname: inputs: specialArgs@{ config, pkgs, lib, name, ... }: let inherit (inputs.self) lib; in let
prefix = inputs.config.prefix;
cfg = config.${prefix}.experiments.noexec;
in {
options.${prefix} = { experiments.noexec = {
enable = lib.mkEnableOption "(almost) all filesystems being mounted as »noexec« (and »nosuid« and »nodev«)";
}; };
config = let
in lib.mkIf cfg.enable (lib.mkMerge [ ({
# This was the only "special" mount that did not have »nosuid« and »nodev« set:
systemd.packages = [ (lib.wip.mkSystemdOverride pkgs "dev-hugepages.mount" "[Mount]\nOptions=nosuid,nodev,noexec\n") ];
# And these were missing »noexec«:
boot.specialFileSystems."/dev".options = [ "noexec" ];
boot.specialFileSystems."/dev/shm".options = [ "noexec" ];
boot.specialFileSystems."/run/keys".options = [ "noexec" ];
# Make all "real" FSs »noexec« (if »wip.fs.temproot.enable = true«):
${prefix}.fs.temproot = let
it = { mountOptions = { nosuid = true; noexec = true; nodev = true; }; };
in { temp = it; local = it; remote = it; };
# Ensure that the /nix/store is not »noexec«, even if the FS it is on is:
boot.initrd.postMountCommands = ''
if ! mountpoint -q $targetRoot/nix/store ; then
mount --bind $targetRoot/nix/store $targetRoot/nix/store
fi
mount -o remount,exec $targetRoot/nix/store
'';
# Nix has no (direct) settings to change where the builders have their »/build« bound to, but many builds will need it to be »exec«:
systemd.services.nix-daemon = { # TODO: while noexec on /tmp is the problem, neither of this solve it:
serviceConfig.PrivateTmp = true;
#serviceConfig.PrivateMounts = true; serviceConfig.ExecStartPre = "/run/wrappers/bin/mount -o remount,exec /tmp";
};
nix.allowedUsers = [ "root" "@wheel" ]; # This goes hand-in-hand with setting mounts as »noexec«. Cases where a user other than root should build stuff are probably fairly rare. A "real" user might want to, but that is either already in the wheel(sudo) group, or explicitly adding that user is pretty reasonable.
boot.postBootCommands = ''
# Make the /nix/store non-iterable, to make it harder for unprivileged programs to search the store for programs they should not have access to:
unshare --fork --mount --uts --mount-proc --pid -- ${pkgs.bash}/bin/bash -euc '
mount --make-rprivate / ; mount --bind /nix/store /nix/store ; mount -o remount,rw /nix/store
chmod -f 1770 /nix/store
chmod -f 751 /nix/store/.links
'
'';
}) ]);
}