Remount Secure

From Kicksecure
< Dev
Jump to navigation Jump to search

Secure Mount Options for better Security Hardening / /etc/fstab modifications by a Linux distribution

Considering the most maintainable, stable solution. See also Dev/maintainability and Stable Version User Experience.

See also:


  • servers
  • desktops
  • initrdless
  • initramfs-tools
  • dracut
  • mkosi-initrd
  • perhaps other init systems
  • OpenVZ (not using initrd?)
  • Qubes
  • systemd-nspawn (not using initrd)

Mount Points[edit]

  • A) API file systems
  • B) real partitions
  • C) directories

Build Tools[edit]

There are at four two major build tools.

These tools are responsible for creating /etc/fstab. That is why changing /etc/fstab by default in Kicksecure as a Linux distribution is difficult.


initrd based mount options hardening[edit]

  • initramfs-tools: /usr/share/initramfs-tools/init
  • dracut: used by Kicksecure by default at time of
    • There is an implementation ins security-misc currently disabled by default.
      • /usr/lib/dracut/modules.d-disabled
      • Was functional.
      • Was said to slow down the boot process.
      • Maybe the slowness issues could be worked on by debugging the script. Tracing, debug output execution times throughout its run. Perhaps parallelization, i.e. running the mount commands into the background.


  • happens at early boot before switch-root into the root file system


  • initrd specific (initramfs-tools vs dracut vs maybe mkosi-initrd or perhaps other init systems)
  • Does not work with initrdless systems, such as:
    • Custom kernel with all modules already compiled-in.
    • Boot / virtualization methods not involving an initrd such as systemd-nspawn, and perhaps docker, OpenVZ.
  • configurability: Not as expected by sysadmins using /etc/fstab. Needs different way to customize.

Systemd drop-in mount options for units that already exist[edit]

For example, /etc/systemd/system/home.mount.d/hardening.conf:


There is a reason we create a configuration file under unit.mount.d and do not do our hardening directly within the unit file unit.mount. There also is a very valid reason we choose to do this under /etc instead of doing everything under /usr/lib and respecting the conventions.

Firstly, we do not create a unit file directly. The goal of having drop in config files for mount option hardening is to be universal. If we create a mount unit, we would make several assumptions. We do not know if the user really has a dedicated partition for our target unit, and even if they do, we do not which one it is. We also do not want to make the assumption that it does not existing and bind it directly. Adding this config file under this path provides many benefits. For example, if there is no dedicated partition for /home on disk, our config file /etc/systemd/system/home.mount.d/hardening.conf has literally no effect. It is a unit configuration extension that does not exist, so it will have no effect. The effect will be there if there is a home.mount unit. Then our hardneing takes place.


  • Systemd drop-in files.
  • No further system specific adjustments and/or configurations required.
  • No shell scripting requried.
  • Hardening what already exists as a mount unit.


  • Can only be used for mount points declared in /etc/fstab.
  • Will not work for API file systems, like /dev/shm, /run, /proc, /sys, etc.
  • minor: systemd dependent
  • minor: drop in files need to be placed in /etc and cannot be placed in /lib, not too conventional for a package
  • configurability: Not as expected by sysadmins using /etc/fstab. Needs different way to customize.

See also:

Systemd drop-in mount units for units that normally do not exist[edit]

This one is a rather tricky one. For example, we might place under the path /usr/lib/systemd/system/var.mount the following file:

Description=Bind Mount /var with no dedicated partition



Now the tricky part is, we want unit to come into effect when there is actually no partition for /var on disk. Should this be the case, this a proper mount unit will be created on start up by the system using the /etc/fstab file. Having this unit under this specific path provides us with this exact functionality. When there is a line in fstab for a partition, a proper moutn unit gets created dynamically that overrides our unit under this path, so it effectively becomes non existent. But if there is no such unit to override us, we take effect and assume that since there is no mount unit to override us, there is no partition on disk for /var, so we can bind it to itself.

Binding partitions to itself is also tricky for other reasons. This is not a real mount. Binding one directory to itself allows us a workaround to make use of the hardened mount options for that said directory. But if we want to bind several path, that may be nested in a way, the order of binding would then be of the essence. Having bound /var to itself before binding /var/tmp will result in a double bind situation that allows several points of acces to /var/tmp. A process that might opened this directory before the second bind might retain access under the options normally meant for /var. Not to mention the extra complexity introduced during boot and shut down with nested bind mounts. So when writing such units, attention must be paid to the order.


  • Systemd drop-in files.
  • No further system specific adjustments and/or configurations required.
  • No shell scripting requried.


  • Can be used only for directories with no dedicated partitions on disk.
  • Will not work for API file systems, like /dev/shm, /run, /proc, /sys, etc.
  • Whether or not it is conventionally acceptable for a package to directly create mount units is unclear.
  • Nested binds need to be configured properly not to break or cause breakage.
  • There 'may' be a time window to access these directories before the bind mount, untested.

systemd kernel parameter based mount options hardening[edit]

/etc/default/grub.d/40_secure-mount.cfg as suggested in thanks to monsieuremre!

# tmp and api file systems
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX systemd.mount-extra=tmpfs:/tmp:[:tmpfs[:defaults,nodev,nosuid,noexec]]"
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX systemd.mount-extra=udev:/dev:[:devtmpfs[:defaults,nosuid,noexec]]"
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX systemd.mount-extra=tmpfs:/dev/shm:[:tmpfs[:defaults,nodev,nosuid,noexec]]"
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX systemd.mount-extra=tmpfs:/run:[:tmpfs[:defaults,nodev,nosuid,noexec]]"

Each field is handled as the corresponding fstab field. This option can be specified multiple times, like the following:


We could also use the system credential fstab.extra to declare a path to our alternative fstab file. Lines in this file would parsed in addition to the usual fstab.


  • Can be used for all mount points.
  • No package owns or modifies the fstab file, reducing implementation and maintenance complexity.
  • Ideal and only way to modify the mount options for API file systems without manually remounting them.


  • (acceptable) increase length of already (for other reasons) lengthy kernel command line.
  • (minor) Newer kernel or systemd version (254) required, while stable Debian uses systemd version 252. (Will fix itself after next Debian stable is out and Kicksecure has been rebased)
  • configurability: Not as expected by sysadmins using /etc/fstab. Needs different way to customize.

Autogenerated alternative /etc/fstab[edit]



  • Not touching /etc/fstab.
  • Not using the old fstab directly.
  • We never call mount.
  • We never remount.
  • Systemd handles everything as usual.
  • Everything mounts securely in the first place.
  • We never manually check anything.
  • All we do is generate a custom fstab from the original one, without modifying or owning it.
  • (minor) Short kernel command line expansion.
  • Can be reverted in grub boot menu by editing kernel command line in case it is broken.
  • configurability: Not as expected by sysadmins using /etc/fstab. Needs different way to customize.


  • Parsing /etc/fstab. Shell scripting required to create alternative /etc/fstab. awk, sed, str_replace, bash while true read loop? That would be the difficult, fragile, messy part.
  • (Unlikely but untested) If the user edits /etc/fstab and uses mount, it might reset the hardened mount options? (Most probably not)
  • Also be confusing for users why mount options are hardened in the first place because these aren't done in the place where everyone would except these. That is in /etc/fstab. Maybe could be mitigated by documenting this fact in original /etc/fstab. Which would be modifying the fstab, which is the very thing we try avoiding.
  • configurability: how to disable /tmp noexec? (Parser can be configured to respect simple config files)
  • Might be confusing for the unaware user.

systemd unit file based mount options hardening[edit]


  • No initrd modifications.


  • Shell scripting.
  • Happens after initrd.
  • configurability: Not as expected by sysadmins using /etc/fstab. Needs different way to customize.
  • ...?

/etc/fstab file based mount options hardening[edit]


  • No initrd modifications.
  • No shell scripting.
  • configurability: As expected by sysadmins. /etc/fstab could be used normally. No special user documentation required.
  • Should be the most robust, stable place as this is traditionally the place to configure this.





/run/user/1000 bypass[edit]

Quote madaidan:

/run/user/1000 bypasses /run's `noexec` as it is its own mount point. We might want to look into restricting that too.


Implementations by Other Operating Systems[edit]

CLIP OS[edit]


Note: Extremely outdated and no more valid or relevant, but still is a good point of reference to understand the underlying concept.



Allow minimal privileges via mount options

  • Noexec on everything possible
  • Nodev everywhere except / and chroot partitions
  • Nosetuid everywhere except /
  • Consider making /var/tmp link to /tmp, or maybe mount –bind option

A reasonable /etc/fstab:

LABEL=/               /               ext3    defaults                      1 1
LABEL=/tmp            /tmp            ext3    defaults,nosuid,noexec,nodev  1 2
LABEL=/var/log/audit  /var/log/audit  ext3    defaults,nosuid,noexec,nodev  1 2
LABEL=/home           /home           ext3    defaults,nosuid,nodev         1 2
LABEL=/var            /var            ext3    defaults,nosuid               1 2
LABEL=/boot           /boot           ext3    defaults,nosuid,noexec,nodev  1 2
/tmp                  /var/tmp        ext3    defaults,bind,nosuid,noexec,nodev  1 2
tmpfs                 /dev/shm        tmpfs   defaults,nosuid,noexec,nodev  0 0
devpts                /dev/pts        devpts  gid=5,mode=620                0 0
sysfs                 /sys            sysfs   defaults                      0 0
proc                  /proc           proc    defaults                      0 0
LABEL=SWAP-sda6       swap            swap    defaults                      0 0



Modifying fstab

Once you have your partitions broken out and sized accordingly, you can begin to restrict the various mount points as much as possible. You should add nodev, noexec, and nosuid wherever possible. An example of a decently restricted /etc/fstab file is below:

/dev/VG_OS/lv_root          /        ext3      defaults     1 1
/dev/VG_OS/lv_tmp           /tmp     ext3      defaults,nosuid,noexec,nodev  1 2
/dev/VG_OS/lv_vartmp        /var/tmp ext3      defaults,nosuid,noexec,nodev 1 2
/dev/data_vol/lv_home       /home    ext3      defaults,nosuid,nodev  1 2
/dev/VG_OS/lv_var           /var     ext3      defaults,nosuid     1 2
/dev/data_vol/lv_web        /var/www ext3      defaults,nosuid,nodev  1 2
/dev/sda1                   /boot    ext3      defaults,nosuid,noexec,nodev  1 2
tmpfs                       /dev/shm tmpfs     defaults 0 0
devpts                      /dev/pts devpts    gid=5,mode=620 0 0
sysfs                       /sys     sysfs     defaults    0 0
proc                        /proc    proc      defaults    0 0
/dev/_VG_OS/lv_swap         swap     swap      defaults    0 0

Obviously you'll need to modify this example to suit your own system. LVM, volume names, labels etc are all subject to change. Please don't copy this example verbatim and expect it to work for you.

The webserver mount can also be set noexec, however this will impact cgi based applications, as well as server side includes which rely on the execute bit hack. If you're not using cgi applications, I would recommend at least testing noexec and using it if there are no negative side-effects.

Arch Linux[edit]

Mount options

Following the principle of least privilege, file systems should be mounted with the most restrictive mount options possible (without losing functionality).

Relevant mount options are:

  • nodev: Do not interpret character or block special devices on the file system.
  • nosuid: Do not allow set-user-identifier or set-group-identifier bits to take effect.
  • noexec: Do not allow direct execution of any binaries on the mounted file system.
    • Setting noexec on /home disallows executable scripts and breaks Wine* and Steam.
    • Some packages (building nvidia-dkms for example) may require exec on /var.
  • Wine does not need the exec flag for opening Windows executables. It is only needed when Wine itself is installed in /home.

File systems used for data should always be mounted with nodev, nosuid and noexec.

Potential file system mounts to consider:

  • /var
  • /home
  • /dev/shm
  • /tmp
  • /boot

Forum Discussion[edit]


Unfinished: This wiki is a work in progress. Please do not report broken links until this notice is removed, use Search Engines First and contribute improving this wiki.

We believe security software like Kicksecure needs to remain Open Source and independent. Would you help sustain and grow the project? Learn more about our 12 year success story and maybe DONATE!