pam-tmpdir-helper breaks certain initramfs-update actions on systems with noexec on the /tmp mount
wryMitts opened this issue · 4 comments
The Bug
Initramfs related bootscripts may not add all dependencies needed for a system to boot when it's build directory has the noexec flag.
On Kicksecure systems still running initramfs
or systems with initramfs-update
installed, the pam-tmpdir-helper
option being used for the root user will move the environment's tmp
directory into /tmp/user/$UID
using the TMPDIR
variable.
If the noexec
flag is also not set for /tmp
, this violates assumptions in mkinitramfs
related scripts, and may prevent boot, per mkinitramfs (9)
The given directory should be on a filesystem which allows the execution of files stored there, i.e. should not be mounted with the noexec mount option.
Environments Impacted
Environments using keyscripts
to unlock LUKS
volumes at bootup may be impacted.
The decrypt_keyctl
keyscript, a default keyscript available in cryptsetup-initramfs
, is used to unlock several LUKS volumes at the same time with the same password. When this keyscript is used, the keyscript itself is added to the initramfs by /etc/crypttab
related hooks, although not all dependencies are added until the later initramfs build process.
The correct dependencies are then added by another script, which runs during the initramfs build. The cryptkeyctl
script checks if the decrypt_keyctl
script is present and executable in the temporary build directory that mkinitramfs
uses.
update-initramfs:
Calling hook cryptkeyctl
+ PREREQ=cryptroot
+ . /usr/share/initramfs-tools/hook-functions
+ [ ! -x /tmp/user/0/mkinitramfs_LhQz6c/lib/cryptsetup/scripts/decrypt_keyctl ]
+ exit 0
Reproduction Instructions
- Ensure /tmp has noexec set.
- Ensure that /etc/pam.d/common-session contains session option pam_tmpdir.so per the recent security-misc patch.
- In your
/etc/crypttab
, add this option: keyscript=decrypt_keyctl so it appears as below:
#<target> <source> <keyfile> <options>
sda_crypt /dev/sda2 main_data_raid luks,discard,keyscript=decrypt_keyctl
- Run update-initramfs
- Reboot
You will get errors about missing dependencies to store the key in the kernel keystore using keyctl
. The system will fail to boot since it attempts to pass an 0-byte password to cryptsetup.
Control test:
For a control test, follow the same instructions, but ensure that noexec is NOT set for /tmp
.
The volume should unlock normally on reboot.
Causes
The default build directory without pam-tmpdir-helper
would otherwise be /var/tmp
, which would otherwise be executable.
This is activated by /etc/pam.d/common-session
, using the session option pam_tmpdir.so
line. I believe the dependency on libpam-tmpdir
creates this line per commit 8e66a41, and the function that adds this is called via /usr/share/pam-configs/tmpdir
in https://packages.debian.org/sid/amd64/libpam-tmpdir/filelist
I am unsure if this issue impacts dracut systems. Dracut seems to use a customizable temporary directory as well, but I have not studied how hook scripts function, or if they even do function.
Fixes?
I will attempt this workaround to exclude the root user:
https://serverfault.com/a/755956
edit: This does not appear to be functioning for session type modules.
Workaround:
Change the script to check if the file exists and contains greater than zero bytes with the -s flag.
if [ ! -s "$DESTDIR/lib/cryptsetup/scripts/decrypt_keyctl" ]; then
exit 0
fi
References
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1062756
https://cryptsetup-team.pages.debian.net/cryptsetup/README.keyctl.html
https://manpages.debian.org/bookworm/initramfs-tools-core/mkinitramfs.8.en.html
I have several hooks on an initramfs system with noexec option on /tmp. Also I use luks and have no problems with that either. Can you provide a little more specific instructions to reproduce any breakage? Like make /tmp noexec and try doing this and it won't work kind of instructions.
I have several hooks on an initramfs system with noexec option on /tmp. Also I use luks and have no problems with that either. Can you provide a little more specific instructions to reproduce any breakage? Like make /tmp noexec and try doing this and it won't work kind of instructions.
I've modified my post to contain those instructions, let me know if you need any more info.
Thanks!
Brainstorming a fix while keeping noexec and pam-tmpdir-helper
It seems that mkimitramfs treats files in /etc/initramfs-tools/conf.d
as shell scripts.
It is not documented, but perhaps we can override TMPDIR
there and switch it back to /var/tmp
or maybe /var/tmp/mkinitramfs
(with our own extra hardening).
https://salsa.debian.org/kernel-team/initramfs-tools/-/blob/master/mkinitramfs?ref_type=heads
https://manpages.debian.org/bookworm/initramfs-tools-core/mkinitramfs.8.en.html
https://manpages.debian.org/bookworm/initramfs-tools-core/initramfs.conf.5.en.html
Thanks for the great report!
Breaking initramfs-tools is pretty bad.
Seems to be an initramfs-tools upstream (or Debian?) bug by not considereding libpam-tmpdirs / /tmp
noexec
.
I re-opened, re-assigned [1] [2] and commented on that Debian bug.
Also (hopefully) reported to upstream:
initramfs-tools broken by libpam-tmpdir and /tmp mounted with noexec
I am not sure this is a blocker for implementing mount options hardening (#157). This is because mounting /tmp
noexec
could be done for Kicksecure builds only which come with dracut by default which does not have this issue. However, then users couldn't easily switch to initramfs-tools which is still pretty bad.
env | grep -i tmp
env | grep -i temp
We'd should set all of TEMP, TEMPDIR, TMP, TMPDIR for consistency because all of these are changed by libpam-tmpdir.
Meanwhile if/until upstream fixes this, a /etc/initramfs-tools/conf.d
based workaround would be good.
[1] Nothing special. Any Debian / e-mail user can do this.
[ 2] https://www.debian.org/Bugs/server-control