Debian GNU/Linux · Filesystem & permissions

Mount separate filesystems with nodev, nosuid and noexec where they are not needed

When it fails: Separate filesystems are mounted without restrictive options. Device files, setuid programs or executables can be used from filesystems that should only hold data.

CB-DEB-FS-006lowactiveautomatedprofile core

Description

When these directories are separate filesystems, they are mounted with the options listed in {{ mount_options }} (format directory:option,option). By default:

DirectoryOptions
/home, /var, /opt, /srvnodev,nosuid
/var/tmp, /var/log, /var/log/audit, /bootnodev,nosuid,noexec
/usrnodev

The hardened profiles also require noexec on /home. Every other local filesystem backed by a block device, except /, must be mounted with nodev. A directory that is not a separate filesystem is skipped; when there is none besides /, the control does not apply.

ANSSI also recommends noexec on /var. It is left out: dpkg runs package maintainer scripts from /var/lib/dpkg/info/, so package installation and upgrades fail with it. Container engines that store images under /var/lib need exec as well.

Rationale

Only /dev needs device files, and only system directories need setuid programs or executables. nodev stops a device node created on a data filesystem (or brought on removable media) from giving raw access to disks or memory. nosuid stops setuid programs planted there from granting privileges, and noexec stops tools dropped there from being run directly.

Impact

noexec on /home (hardened profiles) prevents users from running their own scripts and programs directly, including tools installed under ~/.local/bin. noexec on /boot and /var/log has no known effect on Debian.

Setting

Location/etc/fstab
DefaultOptions chosen at installation (usually defaults)
Recommended{{ mount_options }}; nodev on every other local filesystem except /

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
mount_optionslist. Required options per mount point, as directory:option,option./home:nodev,nosuid, /var:nodev,nosuid, /var/tmp:nodev,nosuid,noexec, /var/log:nodev,nosuid,noexec, /var/log/audit:nodev,nosuid,noexec, /boot:nodev,nosuid,noexec, /opt:nodev,nosuid, /srv:nodev,nosuid, /usr:nodev/home:nodev,nosuid, /var:nodev,nosuid, /var/tmp:nodev,nosuid,noexec, /var/log:nodev,nosuid,noexec, /var/log/audit:nodev,nosuid,noexec, /boot:nodev,nosuid,noexec, /opt:nodev,nosuid, /srv:nodev,nosuid, /usr:nodev/home:nodev,nosuid,noexec, /var:nodev,nosuid, /var/tmp:nodev,nosuid,noexec, /var/log:nodev,nosuid,noexec, /var/log/audit:nodev,nosuid,noexec, /boot:nodev,nosuid,noexec, /opt:nodev,nosuid, /srv:nodev,nosuid, /usr:nodev/home:nodev,nosuid, /var:nodev,nosuid, /var/tmp:nodev,nosuid,noexec, /var/log:nodev,nosuid,noexec, /var/log/audit:nodev,nosuid,noexec, /boot:nodev,nosuid,noexec, /opt:nodev,nosuid, /srv:nodev,nosuid, /usr:nodev/home:nodev,nosuid,noexec, /var:nodev,nosuid, /var/tmp:nodev,nosuid,noexec, /var/log:nodev,nosuid,noexec, /var/log/audit:nodev,nosuid,noexec, /boot:nodev,nosuid,noexec, /opt:nodev,nosuid, /srv:nodev,nosuid, /usr:nodev

The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.

Audit

  1. Run findmnt -kn -o TARGET,SOURCE,OPTIONS.
  2. For each mounted directory of {{ mount_options }}, the options must contain the listed ones.
  3. Every other line whose source is a /dev/ device, except /, must contain nodev.

Automated: every check must pass. Scanners report each check by its id.

options

Mount options of the listed directories and nodev on other local block-device filesystems.

script: |
  rc=0 seen=
  for e in $CB_MOUNT_OPTIONS; do
    p=${e%%:*}
    o=$(findmnt -kn -o OPTIONS --mountpoint "$p" | tail -n 1)
    [ -n "$o" ] || continue
    seen="$seen $p "
    miss=
    for opt in $(printf '%s' "${e#*:}" | tr , ' '); do
      case ,$o, in *,$opt,*) ;; *) miss="$miss $opt" ;; esac
    done
    if [ -z "$miss" ]; then echo "$p: ok"; else echo "$p: missing$miss"; rc=1; fi
  done
  other=$(findmnt -knr -o TARGET,SOURCE,OPTIONS | awk '$2 ~ "^/dev/" && $1 != "/"')
  while read -r t s o; do
    [ -n "$t" ] || continue
    case $seen in *" $t "*) continue ;; esac
    seen="$seen $t "
    case ,$o, in *,nodev,*) echo "$t: ok" ;; *) echo "$t: missing nodev"; rc=1 ;; esac
  done <<EOF
  $other
  EOF
  [ -n "$seen" ] || { echo "no separate filesystem besides /"; exit 2; }
  exit $rc

Remediation

For each reported directory:

  1. Add the missing options to the fourth field of its line in /etc/fstab (for a mount made by a systemd .mount unit, to its Options=).
  2. Run systemctl daemon-reload and mount -o remount <directory>.
  3. Check with findmnt -kn <directory>, and reboot at the next maintenance window to confirm.

Test noexec and nosuid first on systems that run software from /opt, /srv or /home.

References

Mappings

FrameworkIDRelationNote
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R28partialOurs leaves out noexec on /var (breaks dpkg) and noexec on /home outside the hardened profiles.
NIST SP 800-53 Rev. 55.1.1CM-7related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

  • related CB-DEB-FS-005 Put /home, /var, /var/tmp, /var/log and /var/log/audit on separate filesystems
  • related CB-DEB-FS-003 Mount /tmp as a separate filesystem with nodev, nosuid and noexec

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 12, Proxmox VM 922, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. Fails on fresh install (/boot/efi without nodev); not applicable with /boot/efi unmounted; loop-mounted /var/tmp fails without options and passes after remount with nodev,nosuid,noexec.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM 932, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. Fails on fresh install (/boot/efi without nodev); not applicable with /boot/efi unmounted; loop-mounted /var/tmp fails without options and passes after remount with nodev,nosuid,noexec.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr