Add usrquota Option to /home
Description
The usrquota
mount option allows for the filesystem to have disk quotas configured.
Add the usrquota
option to the fourth column of
/etc/fstab
for the line which controls mounting of
/home
.
Rationale
To ensure the availability of disk space on /home, it is important to limit the impact a
single user or group can cause for other users (or the wider system) by intentionally or
accidentally filling up the partition. Quotas can also be applied to inodes for filesystems
where inode exhaustion is a concern.
Shell script
The following script can be run on the host to remediate the issue.
#!/bin/bash
# Remediation is applicable only in certain platforms
if ( [ ! -f /.dockerenv ] && [ ! -f /run/.containerenv ] && findmnt --kernel "/home" > /dev/null || findmnt --fstab "/home" > /dev/null ); then
function perform_remediation {
mount_point_match_regexp="$(printf "^[[:space:]]*[^#].*[[:space:]]%s[[:space:]]" "/home")"
grep "$mount_point_match_regexp" -q /etc/fstab \
|| { echo "The mount point '/home' is not even in /etc/fstab, so we can't set up mount options" >&2;
echo "Not remediating, because there is no record of /home in /etc/fstab" >&2; return 1; }
mount_point_match_regexp="$(printf "^[[:space:]]*[^#].*[[:space:]]%s[[:space:]]" /home)"
# If the mount point is not in /etc/fstab, get previous mount options from /etc/mtab
if ! grep -q "$mount_point_match_regexp" /etc/fstab; then
# runtime opts without some automatic kernel/userspace-added defaults
previous_mount_opts=$(grep "$mount_point_match_regexp" /etc/mtab | head -1 | awk '{print $4}' \
| sed -E "s/(rw|defaults|seclabel|usrquota)(,|$)//g;s/,$//")
[ "$previous_mount_opts" ] && previous_mount_opts+=","
# In iso9660 filesystems mtab could describe a "blocksize" value, this should be reflected in
# fstab as "block". The next variable is to satisfy shellcheck SC2050.
fs_type=""
if [ "$fs_type" == "iso9660" ] ; then
previous_mount_opts=$(sed 's/blocksize=/block=/' <<< "$previous_mount_opts")
fi
echo " /home defaults,${previous_mount_opts}usrquota 0 0" >> /etc/fstab
# If the mount_opt option is not already in the mount point's /etc/fstab entry, add it
elif ! grep "$mount_point_match_regexp" /etc/fstab | grep -q "usrquota"; then
previous_mount_opts=$(grep "$mount_point_match_regexp" /etc/fstab | awk '{print $4}')
sed -i "s|\(${mount_point_match_regexp}.*${previous_mount_opts}\)|\1,usrquota|" /etc/fstab
fi
if mkdir -p "/home"; then
if mountpoint -q "/home"; then
mount -o remount --target "/home"
fi
fi
}
perform_remediation
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
Ansible playbook
The following playbook can be run with Ansible to remediate the issue.
- name: 'Add usrquota Option to /home: Check information associated to mountpoint'
command: findmnt --fstab '/home'
register: device_name
failed_when: device_name.rc > 1
changed_when: false
when: ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman",
"container"] and "/home" in ansible_mounts | map(attribute="mount") | list )
tags:
- CCE-86035-3
- NIST-800-53-CM-6(b)
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_usrquota
- no_reboot_needed
- name: 'Add usrquota Option to /home: Create mount_info dictionary variable'
set_fact:
mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
with_together:
- '{{ device_name.stdout_lines[0].split() | list | lower }}'
- '{{ device_name.stdout_lines[1].split() | list }}'
when:
- ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
and "/home" in ansible_mounts | map(attribute="mount") | list )
- device_name.stdout is defined and device_name.stdout_lines is defined
- (device_name.stdout | length > 0)
tags:
- CCE-86035-3
- NIST-800-53-CM-6(b)
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_usrquota
- no_reboot_needed
- name: 'Add usrquota Option to /home: If /home not mounted, craft mount_info manually'
set_fact:
mount_info: '{{ mount_info|default({})|combine({item.0: item.1}) }}'
with_together:
- - target
- source
- fstype
- options
- - /home
- ''
- ''
- defaults
when:
- ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
and "/home" in ansible_mounts | map(attribute="mount") | list )
- ("--fstab" | length == 0)
- (device_name.stdout | length == 0)
tags:
- CCE-86035-3
- NIST-800-53-CM-6(b)
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_usrquota
- no_reboot_needed
- name: 'Add usrquota Option to /home: Make sure usrquota option is part of the to
/home options'
set_fact:
mount_info: '{{ mount_info | combine( {''options'':''''~mount_info.options~'',usrquota''
}) }}'
when:
- ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
and "/home" in ansible_mounts | map(attribute="mount") | list )
- mount_info is defined and "usrquota" not in mount_info.options
tags:
- CCE-86035-3
- NIST-800-53-CM-6(b)
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_usrquota
- no_reboot_needed
- name: 'Add usrquota Option to /home: Ensure /home is mounted with usrquota option'
mount:
path: /home
src: '{{ mount_info.source }}'
opts: '{{ mount_info.options }}'
state: mounted
fstype: '{{ mount_info.fstype }}'
when:
- ( ansible_virtualization_type not in ["docker", "lxc", "openvz", "podman", "container"]
and "/home" in ansible_mounts | map(attribute="mount") | list )
- (device_name.stdout is defined and (device_name.stdout | length > 0)) or ("--fstab"
| length == 0)
tags:
- CCE-86035-3
- NIST-800-53-CM-6(b)
- configure_strategy
- high_disruption
- low_complexity
- medium_severity
- mount_option_home_usrquota
- no_reboot_needed
Warning
The quota options for XFS file systems can only be activated when mounting the partition.
It is not possible to enable them by remounting an already mounted partition. Therefore,
if the desired options were not defined before mounting the partition, dismount and mount
it again to apply the quota options.