#!/bin/bash ## Copyright (C) 2019 - 2023 ENCRYPTED SUPPORT LP ## See the file COPYING for copying conditions. ## noexec in /tmp and/or /home can break some malware but also legitimate ## applications. ## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707 #set -x set -e set -o pipefail set -o nounset init() { if test -o xtrace ; then output_command=true else output_command=echo fi if [ "$(id -u)" != "0" ]; then $output_command "ERROR: must be run as root! sudo $0" exit 1 fi $output_command "START" mkdir --parents "/run/remount-secure" exit_code=0 ## Debugging. $output_command "INFO: 'findmnt --list' output at the START." $output_command "$(findmnt --list)" $output_command "" } parse_options() { ## Thanks to: ## http://mywiki.wooledge.org/BashFAQ/035 while : do case ${1:-} in --remountnoexec) $output_command "INFO: --remountnoexec" noexec_maybe=",noexec" shift ;; --force) $output_command "INFO: --force" option_force=true shift ;; --) shift break ;; -*) echo "unknown option: $1" >&2 exit 1 ;; *) break ;; esac done [[ -v noexec_maybe ]] || noexec_maybe="" [[ -v option_force ]] || option_force="" } remount_secure() { $output_command "" ## ${FUNCNAME[1]} is the name of the calling function. I.e. the function ## which called this function. status_file_name="${FUNCNAME[1]}" ## example status_file_name: ## _home status_file_full_path="/run/remount-secure/${status_file_name}" ## example status_file_full_path: ## /run/remount-secure/_home old_mount_options="$(findmnt --noheadings --output options -- "$mount_folder")" || true ## example old_mount_options: ## rw,nosuid,nodev,relatime,discard $output_command "INFO: '$mount_folder' old_mount_options: '$old_mount_options'" if echo "$old_mount_options" | grep --quiet "$intended_mount_options" ; then $output_command "INFO: '$mount_folder' has already intended mount options. ($intended_mount_options)" return 0 fi ## When this package is upgraded, the systemd unit will run again. ## If the user meanwhile manually relaxed mount options, this should not be undone. if [ ! "$option_force" == "true" ]; then if [ -e "$status_file_full_path" ]; then $output_command "INFO: '$mount_folder' already remounted earlier. Not remounting again. Use --force if this is what you want." return 0 fi fi if findmnt --noheadings "$mount_folder" >/dev/null ; then $output_command "INFO: '$mount_folder' already mounted, therefore using remount." $output_command INFO: Executing: mount --options "remount,${intended_mount_options}" "$mount_folder" mount --options "remount,${intended_mount_options}" "$mount_folder" || exit_code=100 else $output_command "INFO: '$mount_folder' not yet mounted, therefore using mount bind." $output_command INFO: Executing: mount --options "$intended_mount_options" --bind "$mount_folder" "$mount_folder" mount --options "$intended_mount_options" --bind "$mount_folder" "$mount_folder" || exit_code=101 fi new_mount_options="$(findmnt --noheadings --output options -- "$mount_folder")" || true $output_command "INFO: '$mount_folder' new_mount_options: $new_mount_options" touch "$status_file_full_path" } _run() { mount_folder="/run" ## https://lists.freedesktop.org/archives/systemd-devel/2015-February/028456.html intended_mount_options="nosuid,nodev${noexec_maybe}" remount_secure "$@" } _dev_shm() { mount_folder="/dev/shm" intended_mount_options="nosuid,nodev${noexec_maybe}" remount_secure "$@" } _tmp() { mount_folder="/tmp" intended_mount_options="nosuid,nodev${noexec_maybe}" remount_secure "$@" } ## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707/25 # _lib() { # mount_folder="/lib" # ## Not using noexec on /lib. # intended_mount_options="nosuid,nodev" # remount_secure "$@" # } _home() { mount_folder="/home" intended_mount_options="nosuid,nodev${noexec_maybe}" remount_secure "$@" } end() { ## Debugging. $output_command "INFO: 'findmnt --list' output at the END." $output_command "$(findmnt --list)" exit $exit_code } main() { init "$@" parse_options "$@" _run "$@" _dev_shm "$@" _tmp "$@" #_lib "$@" _home "$@" end "$@" } main "$@"