#!/bin/bash # SPDX-Version: 3.0 # SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; # SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git # SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency # SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; # SPDX-FileType: SOURCE # SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0 # SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework. # SPDX-PackageName: CISS.debian.installer # SPDX-Security-Contact: security@coresecret.eu guard_sourcing ####################################### # '/etc/fstab' entry writer and logger. # Globals: # TARGET # Arguments: # 1: UUID # 2: Mount Path # 3: Filesystem # 4: Mount Options # 5: Pass value, while Dump value is hardcoded always "0", e.g., "1" # Returns: # 0: on success ####################################### write_fstab() { declare _uuid="$1" _path="$2" _fs="$3" _opts="$4" _pass="$5" printf "UUID=%s %s %s %s 0 %s\n" "${_uuid}" "${_path}" "${_fs}" "${_opts}" "${_pass}" >> "${TARGET}/etc/fstab" do_log "info" "true" "fstab entry generated: 'UUID=${_uuid} ${_path} ${_fs} ${_opts} 0 ${_pass}'." return 0 } ####################################### # Generate target '/etc/fstab' entries. # Globals: # HMP_EPHEMERAL_ENCLABEL # HMP_PATH_FSUUID # MAP_MOUNTPATH_DEV # TARGET # VAR_RECIPE_STRING # VAR_SETUP_PART # Arguments: # None # Returns: # 0: on success ####################################### generate_fstab() { ### Generate '${TARGET}/etc/fstab' header. : >| "${TARGET}/etc/fstab" chmod 0600 "${TARGET}/etc/fstab" cat << 'EOF' >> "${TARGET}/etc/fstab" # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # systemd generates mount units based on this file, see systemd.mount(5). # Please run 'systemctl daemon-reload' after making changes here. # # # Secure tmpfs mounts for a hardened system # Mount the proc filesystem to provide process and kernel information proc /proc proc nodev,nosuid,noexec,hidepid=2 0 0 # Mount sysfs to expose kernel device information to user space sysfs /sys sysfs defaults 0 0 # Mount the devpts filesystem to enable pseudo-terminal support for user sessions devpts /dev/pts devpts gid=5,mode=620 0 0 # Restrict /dev/shm to shared memory, limit size, prevent code execution tmpfs /dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,size=1G 0 0 # System runtime directory in RAM; do not set noexec here for compatibility tmpfs /run tmpfs mode=0755,nodev,nosuid 0 0 EOF ### Generate '${TARGET}/etc/fstab' special entries '/' '/boot' '/boot/efi'. ### Define the order of the special paths. declare -a ary_path_order; ary_path_order=("/" "/boot" "/boot/efi") declare -a ary_skip=("/" "/boot" "/boot/efi" "/recovery") declare var_path var_entry var_part var_dev var_key var_uuid var_fs_btrfs_compress var_fs_btrfs_level var_fs_btrfs_subvolume \ var_fs_version var_mount_options var_mount_optsnap var_btrfs_compression for var_path in "${ary_path_order[@]}"; do var_entry=$(yq e -r '.recipe.*.dev.* | select(.mount.path == "'"${var_path}"'")' "${VAR_SETUP_PART}") if [[ -z "${var_entry}" ]]; then continue fi var_part=$(echo "${var_entry}" | yq e 'path | .[-2]' -) var_dev=$(echo "${var_entry}" | yq e 'path | .[-3]' -) var_key="UUID_${var_path}" var_uuid="${HMP_PATH_FSUUID[${var_key}]}" var_fs_btrfs_compress=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.btrfs.compress" "${VAR_SETUP_PART}") var_fs_btrfs_level=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.btrfs.level" "${VAR_SETUP_PART}") var_fs_btrfs_subvolume=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.btrfs.subvolume" "${VAR_SETUP_PART}") var_fs_version=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.version" "${VAR_SETUP_PART}") var_mount_options=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.mount.options" "${VAR_SETUP_PART}") var_mount_optsnap=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.mount.optsnap" "${VAR_SETUP_PART}") if [[ "${var_fs_version,,}" == btrfs ]]; then if [[ "${var_fs_btrfs_level:-0}" == 0 ]]; then var_btrfs_compression="compress=no" else var_btrfs_compression="compress=${var_fs_btrfs_compress}:${var_fs_btrfs_level}" fi write_fstab "${var_uuid}" "${var_path}" "${var_fs_version}" "${var_mount_options},${var_btrfs_compression}" "1" if [[ -n "${var_fs_btrfs_subvolume}" ]]; then if [[ "${var_path}" == "/" ]]; then write_fstab "${var_uuid}" "/.snapshots" "${var_fs_version}" "${var_mount_optsnap}" "0" else write_fstab "${var_uuid}" "${var_path}/.snapshots" "${var_fs_version}" "${var_mount_optsnap}" "0" fi fi continue elif [[ "${var_fs_version,,}" == ext4 ]]; then write_fstab "${var_uuid}" "${var_path}" "${var_fs_version}" "${var_mount_options}" "1" continue elif [[ "${var_fs_version,,}" == fat32 ]]; then write_fstab "${var_uuid}" "${var_path}" "vfat" "${var_mount_options}" "2" continue fi done ### Generate '${TARGET}/etc/fstab' remaining entries. for var_path in "${!MAP_MOUNTPATH_DEV[@]}"; do if validation_array "${var_path}" "${ary_skip[@]}"; then continue fi var_entry=$(yq e -r '.recipe.*.dev.* | select(.mount.path == "'"${var_path}"'")' "${VAR_SETUP_PART}") if [[ -z "${var_entry}" ]]; then continue fi var_part=$(echo "${var_entry}" | yq e 'path | .[-2]' -) var_dev=$(echo "${var_entry}" | yq e 'path | .[-3]' -) var_key="UUID_${var_path}" var_uuid="${HMP_PATH_FSUUID[${var_key}]}" var_fs_btrfs_compress=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.btrfs.compress" "${VAR_SETUP_PART}") var_fs_btrfs_level=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.btrfs.level" "${VAR_SETUP_PART}") var_fs_btrfs_subvolume=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.btrfs.subvolume" "${VAR_SETUP_PART}") var_fs_version=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.filesystem.version" "${VAR_SETUP_PART}") var_mount_options=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.mount.options" "${VAR_SETUP_PART}") var_mount_optsnap=$(yq_val ".recipe.${VAR_RECIPE_STRING}.dev.${var_dev}.${var_part}.mount.optsnap" "${VAR_SETUP_PART}") if [[ "${var_fs_version,,}" == btrfs ]]; then if [[ "${var_fs_btrfs_level:-0}" == 0 ]]; then var_btrfs_compression="compress=no" else var_btrfs_compression="compress=${var_fs_btrfs_compress}:${var_fs_btrfs_level}" fi write_fstab "${var_uuid}" "${var_path}" "${var_fs_version}" "${var_mount_options},${var_btrfs_compression}" "2" if [[ -n "${var_fs_btrfs_subvolume}" ]]; then write_fstab "${var_uuid}" "${var_path}/.snapshots" "${var_fs_version}" "${var_mount_optsnap}" "0" fi continue elif [[ "${var_fs_version,,}" == ext4 ]]; then write_fstab "${var_uuid}" "${var_path}" "${var_fs_version}" "${var_mount_options}" "2" continue elif [[ "${var_fs_version,,}" == fat32 ]]; then write_fstab "${var_uuid}" "${var_path}" "vfat" "${var_mount_options}" "2" continue fi done cat << 'EOF' >> "${TARGET}/etc/fstab" /dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0 EOF do_log "info" "true" "fstab entry generated: '/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0'." ### Add entry for 'SWAP' device. var_path="SWAP" write_fstab "/dev/mapper/${HMP_EPHEMERAL_ENCLABEL["${var_path}"]}" "none" "swap" "defaults" "0" ### Add entry for '/tmp' device. var_path="/tmp" write_fstab "/dev/mapper/${HMP_EPHEMERAL_ENCLABEL["${var_path}"]}" "/tmp" "ext4" "defaults,rw,nodev,nosuid,relatime" "0" return 0 } # vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh