Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pam-tmpdir-helper breaks certain initramfs-update actions on systems with noexec on the /tmp mount #198

Open
wryMitts opened this issue Feb 3, 2024 · 4 comments

Comments

@wryMitts
Copy link
Contributor

wryMitts commented Feb 3, 2024

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

  1. Ensure /tmp has noexec set.
  2. Ensure that /etc/pam.d/common-session contains session option pam_tmpdir.so per the recent security-misc patch.
  3. 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
  1. Run update-initramfs
  2. 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

@monsieuremre
Copy link
Contributor

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.

@wryMitts
Copy link
Contributor Author

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!

@wryMitts
Copy link
Contributor Author

wryMitts commented Feb 13, 2024

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

@adrelanos
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants