pam_mount and SELinux
On all my computers, my personal data is encrypted. It is mostly a piece-of-mind thing as I do not want the average burglar to go through my files. For my laptop, full disk encryption (FDE) is not really a problem: I am the only one using it. Therefore I can enter the passphrase at boot and be done with it. Fedora (and Ubuntu) offer a nice checkbox to fully encrypt the drives at installation time.
For a shared computer, this poses a significant problem. If I perform FDE,
nobody but me can boot up the machine. So there must be a way to encrypt just
my files. Years ago I have used eCryptFS for this. It works quite nice and
is an installation option in Ubuntu. Your /home
directory is then encrypted
per-file. This means that no giant image file is sitting around which needs
to be shrunk down occasionally, like FileVault on Mac OS X 10.5. The
downsides are that this limits the length of file names and does not seem to
leverage the AES-NI instruction set. While using a HDD, this cannot be noticed.
But with an SSD, the CPU will suddenly become the bottleneck. Therefore I had
to do something else.
Fedora has solved the per-user file encryption with an encrypted image file. I have not tried that yet, but it seems to circumvent the above issues. The downside is that the image file has to resized occasionally, I believe. The option that I have settled for is an extra partition which is encrypted with LUKS. This probably does not differ much from the approach that I know from the older Fedora installers.
LUKS
LUKS are helpers and utilities that make dm-crypt
more easy to use. First you
should create a partition somewhere, encrypt it with LUKS (cryptsetup ...
)
and then create a filesystem (mkfs.ext4
or mkfs.btrfs
) on it.
The passphrase on the LUKS volume has to be exactly the same as your login password. Otherwise the automatic mounting (which is set up in the text below) will not work.
pam_mount
pam_mount
is a nice utility/library that allows you to mount certain volumes
when a user logs in. I would have my own partition encrypted with LUKS that
pam_mount
will mount into /home/mu
for me. The setup has to be done by
hand.
Defaults on Fedora, Arch Linux and Ubuntu
On Ubuntu I managed to do this rather easily. I am not sure what exactly I did
but a line added in /etc/security/pam_mount.conf.xml
was needed for the
volume and the mount point. On Fedora there was no pam_mount.so
entry in any
of the files in /etc/pam.d
. Therefore I had to add them. The documentation
you find on the web is for various distributions and various versions of pam.
This is bad as you now really have to understand what\'s going on.
I am not opposed of understanding things, quite the opposite. But I am against the need of understanding everything. This is why I use Fedora or Ubuntu instead of Arch Linux. I am happy to use a system and not understand why it works in certain aspects as long as it does its job.
Anyway, there are a lot of files in /etc/pam.d
:
-rw-r--r--. 1 root root 272 17. Jun 2015 atd -rw-r--r--. 1 root root 192 18. Nov 12:28 chfn -rw-r--r--. 1 root root 192 18. Nov 12:28 chsh -rw-r--r--. 1 root root 232 12. Aug 17:40 config-util -rw-r--r--. 1 root root 293 13. Jul 13:37 crond -r--r--r--. 1 root root 146 2. Dez 16:45 cups -rw-r--r--. 1 root root 71 2. Nov 18:39 exim lrwxrwxrwx. 1 root root 19 25. Okt 18:18 fingerprint-auth -> fingerprint-auth-ac -rw-r--r--. 1 root root 702 25. Okt 18:18 fingerprint-auth-ac -rw-r--r--. 1 root root 127 17. Jun 2015 hddtemp -rw-r--r--. 1 root root 159 20. Mai 2015 i3lock -rw-r--r--. 1 root root 134 8. Jul 2008 kcheckpass -r--r-xr-x. 1 root root 798 28. Dez 17:13 kde* -rw-r--r--. 1 root root 134 8. Jul 2008 kscreensaver -rw-r--r--. 1 root root 70 17. Dez 03:17 ksu -rw-r--r--. 1 root root 963 10. Sep 19:45 lightdm -rw-r--r--. 1 root root 698 10. Sep 19:45 lightdm-autologin -rw-r--r--. 1 root root 409 8. Apr 2014 lightdm-greeter -rw-r--r--. 1 root root 97 22. Okt 22:03 liveinst -rw-r--r--. 1 root root 715 18. Nov 12:28 login -rw-r--r--. 1 root root 564 25. Nov 00:12 mock -rw-r--r--. 1 root root 154 12. Aug 17:40 other -rw-r--r--. 1 root root 188 18. Jun 2015 passwd lrwxrwxrwx. 1 root root 16 25. Okt 18:18 password-auth -> password-auth-ac -rw-r--r--. 1 root root 974 25. Okt 18:18 password-auth-ac -rw-r--r--. 1 root root 510 18. Dez 21:44 pluto -rw-r--r--. 1 root root 155 14. Jul 23:27 polkit-1 lrwxrwxrwx. 1 root root 12 25. Okt 18:18 postlogin -> postlogin-ac -rw-r--r--. 1 root root 326 25. Okt 18:18 postlogin-ac -rw-r--r--. 1 root root 144 18. Jun 2015 ppp -rw-r--r--. 1 root root 640 18. Nov 12:28 remote
But with an SSD, the CPU will suddenly become the bottleneck. Therefore I had to do something else.
Fedora has solved the per-user file encryption with an encrypted image file. I have not tried that yet, but it seems to circumvent the above issues. The downside is that the image file has to resized occasionally, I believe. The option that I have settled for is an extra partition which is encrypted with LUKS. This probably does not differ much from the approach that I know from the older Fedora installers.
LUKS
LUKS are helpers and utilities that make dm-crypt
more easy to use. First you
should create a partition somewhere, encrypt it with LUKS (cryptsetup ...
)
and then create a filesystem (mkfs.ext4
or mkfs.btrfs
) on it.
The passphrase on the LUKS volume has to be exactly the same as your login password. Otherwise the automatic mounting (which is set up in the text below) will not work.
pam_mount
pam_mount
is a nice utility/library that allows you to mount certain volumes
when a user logs in. I would have my own partition encrypted with LUKS that
pam_mount
will mount into /home/mu
for me. The setup has to be done by
hand.
Defaults on Fedora, Arch Linux and Ubuntu
On Ubuntu I managed to do this rather easily. I am not sure what exactly I did
but a line added in /etc/security/pam_mount.conf.xml
was needed for the
volume and the mount point. On Fedora there was no pam_mount.so
entry in any
of the files in /etc/pam.d
. Therefore I had to add them. The documentation
you find on the web is for various distributions and various versions of pam.
This is bad as you now really have to understand what\'s going on.
I am not opposed of understanding things, quite the opposite. But I am against the need of understanding everything. This is why I use Fedora or Ubuntu instead of Arch Linux. I am happy to use a system and not understand why it works in certain aspects as long as it does its job.
Anyway, there are a lot of files in /etc/pam.d
:
-rw-r--r--. 1 root root 272 17. Jun 2015 atd -rw-r--r--. 1 root root 192 18. Nov 12:28 chfn -rw-r--r--. 1 root root 192 18. Nov 12:28 chsh -rw-r--r--. 1 root root 232 12. Aug 17:40 config-util -rw-r--r--. 1 root root 293 13. Jul 13:37 crond -r--r--r--. 1 root root 146 2. Dez 16:45 cups -rw-r--r--. 1 root root 71 2. Nov 18:39 exim lrwxrwxrwx. 1 root root 19 25. Okt 18:18 fingerprint-auth -> fingerprint-auth-ac -rw-r--r--. 1 root root 702 25. Okt 18:18 fingerprint-auth-ac -rw-r--r--. 1 root root 127 17. Jun 2015 hddtemp -rw-r--r--. 1 root root 159 20. Mai 2015 i3lock -rw-r--r--. 1 root root 134 8. Jul 2008 kcheckpass -r--r-xr-x. 1 root root 798 28. Dez 17:13 kde* -rw-r--r--. 1 root root 134 8. Jul 2008 kscreensaver -rw-r--r--. 1 root root 70 17. Dez 03:17 ksu -rw-r--r--. 1 root root 963 10. Sep 19:45 lightdm -rw-r--r--. 1 root root 698 10. Sep 19:45 lightdm-autologin -rw-r--r--. 1 root root 409 8. Apr 2014 lightdm-greeter -rw-r--r--. 1 root root 97 22. Okt 22:03 liveinst -rw-r--r--. 1 root root 715 18. Nov 12:28 login -rw-r--r--. 1 root root 564 25. Nov 00:12 mock -rw-r--r--. 1 root root 154 12. Aug 17:40 other -rw-r--r--. 1 root root 188 18. Jun 2015 passwd lrwxrwxrwx. 1 root root 16 25. Okt 18:18 password-auth -> password-auth-ac -rw-r--r--. 1 root root 974 25. Okt 18:18 password-auth-ac -rw-r--r--. 1 root root 510 18. Dez 21:44 pluto -rw-r--r--. 1 root root 155 14. Jul 23:27 polkit-1 lrwxrwxrwx. 1 root root 12 25. Okt 18:18 postlogin -> postlogin-ac -rw-r--r--. 1 root root 326 25. Okt 18:18 postlogin-ac -rw-r--r--. 1 root root 144 18. Jun 2015 ppp -rw-r--r--. 1 root root 640 18. Nov 12:28 remote -rw-r--r--. 1 root root 143 18. Nov 12:28 runuser -rw-r--r--. 1 root root 138 18. Nov 12:28 runuser-l -rw-r--r--. 1 root root 835 16. Nov 18:45 sddm -rw-r--r--. 1 root root 549 16. Nov 18:45 sddm-autologin -rw-r--r--. 1 root root 397 4. Nov 21:41 sddm-greeter -rw-r--r--. 1 root root 145 19. Jun 2015 setup lrwxrwxrwx. 1 root root 17 25. Okt 18:18 smartcard-auth -> smartcard-auth-ac -rw-r--r--. 1 root root 752 25. Okt 18:18 smartcard-auth-ac lrwxrwxrwx. 1 root root 25 2. Dez 15:09 smtp -> /etc/alternatives/mta-pam -rw-r--r--. 1 root root 76 12. Okt 12:25 smtp.postfix -rw-r--r--. 1 root root 904 18. Dez 15:20 sshd -rw-r--r--. 1 root root 540 18. Nov 12:28 su -rw-r--r--. 1 root root 238 5. Nov 10:47 sudo -rw-r--r--. 1 root root 178 5. Nov 10:47 sudo-i -rw-r--r--. 1 root root 137 18. Nov 12:28 su-l lrwxrwxrwx. 1 root root 14 25. Okt 18:18 system-auth -> system-auth-ac -rw-r--r--. 1 root root 1015 25. Okt 18:18 system-auth-ac -rw-r--r--. 1 root root 129 14. Dez 12:36 systemd-user -rw-r--r--. 1 root root 84 14. Dez 10:28 vlock -rw-r--r--. 1 root root 276 2. Okt 00:29 vmtoolsd -rw-r--r--. 1 root root 163 16. Nov 11:10 xserver
So where should the lines go? I looked into the working Ubuntu configuration on
another computer and found that the files which contain pam_mount.so
are not
even present in Fedora. The Arch Linux wiki also has a page about pam_mount
but that did not help that much either.
Simon uses Arch Linux and has one computer configured with pam_mount
. I
called him and we looked into the files a bit more closely. Most of them
contain similar looking lines that load some .so
file in one way or another.
There are also some include directives used to obtain the contents of other
files. In the end we drowned in dependencies.
As the file syntax is rather easy I quickly wrote a Python program that parses
the files and outputs a dependency graph to use with GraphViz. The idea is
simple: Whenever the word include
or substack
are used, the module loaded
is an included file. If the line starts with @include
the other file is
included.
On my Fedora machine the dependencies look like the following:
So which file should all this go into? A common suggestion has been the
system-auth
file. The problem is that on Fedora this is automatically
generated by a program called authconfig
. Therefore one should not touch
that. One
tutorial
suggests to do that, however. Another Arch BBS
post discourages the use of
the system-auth
file but that is on Arch Linux.
How do the files look like on Arch Linux?
This is much simpler! And here you can more clearly see why the Arch
system-auth
is too high in the chain, every other service will get those
settings as well. You only want to display manager, ssh remote and local login
to get those settings. The systemd-user
part should not be affected as this
apparently leads to errors unmounting the encrypted drive after logout.
On Arch Linux the choices would be to add the needed lines into
system-remote-login
and system-local-login
. Fedora does not have these
files. Therefore I decided to manually put the lines into sshd
and lightdm
(my display manager).
How does that look on Ubuntu? Well, it\'s complicated:
To be honest, I do not understand why this is so much more complicated. Perhaps
the Ubuntu has lots of more options prepared already? The pam_mount.so
was
already included everywhere as optional
which means that once I installed it
the system was already done. Perhaps Arch Linux only includes the
configurations which are strictly needed and Fedora has a couple more for
convenience but not all them.
Just out of curiosity I also wanted to see how the .so
modules behave in
their dependencies, especially which file the pam_mount.so
got included in.
Therefore I extended the generation script just a little bit.
Then for Fedora we get the following. I marked pam_mount.so
with a red box.
The problem is that it is not connected to anything as this is run on my laptop
without configuring pam_mount
at all. On the other machine I actually
configured it on it would be connected to sshd
and lightdm
. All the images
are SVG, so you can just open them in a new tab and enlarge as you like.
And on Arch Linux it is a little bit simpler. This was also taken from Simon\'s
laptop which also has full disk encryption instead of pam_mount
. On his other
laptop it would be connected to system-local-login
and system-remote-login
.
And Ubuntu it is as complicated as on Fedora. There the pam_mount.so
is
actually attached. The configuration files that ship with Ubuntu have it
already listed.
Those were made with neato
instead of dot
as the hierarchy just got too big
and intertwined.
SELinux
This has worked fine on Ubuntu 15.10 and then on Fedora 23. With Fedora 24, I
was not able to log in any more. In the syslog (see with journalctl
) I was
able to find messages of this kind:
setroubleshoot[1534]: SELinux is preventing lightdm from getattr access on the file /run/mount/utab. For complete SELinux messages. run sealert -l a6e46e7e-628d-427> python3[1534]: SELinux is preventing lightdm from getattr access on the file /run/mount/utab. ***** Plugin catchall (100. confidence) suggests ************************** If you believe that lightdm should be allowed getattr access on the utab file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # ausearch -c 'lightdm' --raw | audit2allow -M my-lightdm # semodule -X 300 -i my-lightdm.pp
Running the ausearch
command at the bottom gave me a policy file that I could
install. This would have fixed this particular problem. However, I want to
deploy this with Ansible on at least two computers and I do not want to clutter
my system with bunch of locally installed SELinux policies. Therefore I did the
following:
- Try to login, observe the errors with
journalctl -f
. - Run
ausearch ... | audit2allow ...
and generate a source policy file.te
. - Insert this policy using Ansible (see below).
- Repeat ...
After a while I had the following policy extracted:
::: {.literalinclude language="text"} lightdm-utab.te :::
In hindsight it would have been easier to switch lightdm
into permissive mode
and then just record all needed policy changes in one go. Now it is too late
but the result is the same.
This policy needs to be compiled. In a really helpful presentation I have found the command needed to compile it:
make -f /usr/share/selinux/devel/Makefile POLICY.pp
Then you install it like this:
/usr/sbin/semodule --install POLICY.pp
In the slides, there is -u
used, but that is deprecated on Fedora 24.
With all this in place, it would still not work. The problem is that creating a
directory for a different process and user is something that can cause nasty
race conditions. Here it is wanted, so the boolean named
polyinstantiation_enabled
has to be enabled.
Like with lightdm, some adjustments need to be done for the SSH server as well. The policy is quite similar. Look into the git repository below for all the details.
Deployment with Ansible
There is nothing better than executable documentation; namely having a readable
script that will perform all the needed actions. Perhaps easiest would be to
check out the pam_mount-crypt
role in my playbooks.
The relevant tasks for pam_mount
are the following on Fedora:
- name: Add mount of {{ dev }} for mu lineinfile: dest: /etc/security/pam_mount.conf.xml line: '<volume user="mu" fstype="crypt" path="{{ dev }}" mountpoint="/home/mu" options="fsck,noatime" />' insertbefore: '</pam_mount>' - name: Include pam_mount in pam config lineinfile: dest: /etc/pam.d/login line: '@include common-pammount' state: absent - name: auth in sshd lineinfile: dest: /etc/pam.d/{{ item.file }} backup: yes state: present line: '{{ item.line }}' insertafter: '{{ item.after }}' with_items: - { file: sshd, line: 'auth optional pam_mount.so', after: '#%PAM-1.0' } - { file: sshd, line: 'session optional pam_mount.so', after: 'pam_selinux.so close' } - { file: lightdm, line: 'auth optional pam_mount.so', after: '#%PAM-1.0' } - { file: lightdm, line: 'session optional pam_mount.so', after: 'pam_selinux.so close' }
The variable dev
contains the device like /dev/sda3
which contains the LUKS
encrypted partition.
The SELinux part is done with this:
- name: Creating selinux custom policy drop folder file: path={{ custom_selinux_dir }} state=directory owner=root group=root mode=0750 - name: Copy custom policies copy: src="{{ item }}.te" dest="{{ custom_selinux_dir }}/{{ item }}.te" with_items: "{{ policies }}" register: custom_policies_output - name: Compile policies command: make -f /usr/share/selinux/devel/Makefile "{{ item.item }}.pp" args: chdir: "{{ custom_selinux_dir }}" when: item.changed with_items: "{{ custom_policies_output.results }}" - name: Load custom SELinux policies shell: /usr/sbin/semodule --install "{{ custom_selinux_dir }}/{{ item.item }}.pp" when: item.changed with_items: "{{ custom_policies_output.results }}" - name: Enable boolean seboolean: name: polyinstantiation_enabled persistent: yes state: yes
For this to work you need a couple packages:
- libselinux-python
- pam_mount
- policycoreutils
- selinux-policy-devel
And the variables used are:
custom_selinux_dir: /etc/selinux/local-policies policies: - lightdm-utab - sshd-utab
Using the Ansible role or by performing all the tasks manually, you should be able to get an encrypted partition mounted for you at login.