#!/bin/bash # Copyright (c) 2016 Xavier G. <xavier.prooties@kindwolf.org> # This program is free software. It comes without any warranty, to the extent # permitted by applicable law. You can redistribute it and/or modify it under # the terms of the Do What The Fuck You Want To Public License, Version 2, as # published by Sam Hocevar. See http://www.wtfpl.net/ for more details. function exit_with_message { echo "${2}" exit "${1}" } function mk_dir { local path="${1}" local mode="${2}" mkdir -p "${path}" || \ exit_with_message 126 \ "Unable to create the following directory, aborting: ${path}" chmod "${mode}" "${path}" || \ exit_with_message 125 \ "Unable to chmod the following directory, aborting: ${path}" } # This script may rely on its invoked name to fetch extra configuration # directives. invoked_name="$(basename "${0}")" # By default, invoke "proot" and "firefox": proot_path="$(which 'proot')" browser_path='firefox' # Base directory for our crap work_dir_base="/run/user/$(id -u)/browser-wrapper" mk_dir "${work_dir_base}" 0700 work_dir="$(mktemp --directory "${work_dir_base}/$$.XXXXXXXX")" || \ exit_with_message 110 "Unable to create working directory, aborting." # Directory to replace /home slash_home_dir="${work_dir}/slash_home" # Directory to replace $HOME home_dir="${work_dir}/home" # Directory to replace /tmp tmp_dir="${work_dir}/tmp" # Empty dir to replace /dev dev_dir="${work_dir}/dev" # Directory for uploads upload_dir="${HOME}/Uploads" # Directory for downloads download_dir="${HOME}/Downloads" for directory in {{slash_,}home,tmp,{up,down}load,dev}_dir; do mk_dir "${!directory}" 0700 done # Leverage proot to make the browser believe that: # - some directories located right under the root, such as /boot, /root and # /srv, are absent as they are not expected to be of any use to any web # browser. root_dir_options=" --bind=/dev/null:/boot \ --bind=/dev/null:/root \ --bind=/dev/null:/srv" # - /home is either empty or contains only our home slash_home_options="--bind=${slash_home_dir}:/home" # - the home directory is almost empty home_options="--bind=${home_dir}:${HOME}" # - its configuration directory is still there # - its cache directory is still there browser_conf_options=" --bind=${HOME}/.mozilla/firefox:${HOME}/.mozilla/firefox \ --bind=${HOME}/.cache/mozilla/firefox:${HOME}/.cache/mozilla/firefox" # - its download directory is still there # (at least the one for English speakers) download_options="--bind=${download_dir}:${HOME}/Downloads" # - a ~/Uploads directory is present upload_options="--bind=${upload_dir}:${HOME}/Uploads" # - ~/.adobe and ~/.macromedia are still there # (for the sake of Flash Player and other plugins) adobe_options=" --bind=${HOME}/.adobe:${HOME}/.adobe \ --bind=${HOME}/.macromedia:${HOME}/.macromedia" # - various directories related to Java applets are still there # (assuming IcedTea-Web >= 1.5 / OpenJDK) java_options=" --bind=${HOME}/.config/icedtea-web:${HOME}/.config/icedtea-web --bind=${HOME}/.cache/icedtea-web:${HOME}/.cache/icedtea-web --bind=${HOME}/.java:${HOME}/.java --bind=${HOME}/.local/share/applications/javaws:${HOME}/.local/share/application/javaws" # - /tmp is empty # (as in: do not even try to mess with the Unix sockets to ssh-agent) tmp_options="--bind=${tmp_dir}:/tmp" # - /sys is simply absent # (Firefox tries to reach various things under /sys/devices/system/ but # seems to cope without it) sys_options="--bind=/dev/null:/sys" # - /proc is still there, unless you want to hit that very detailed error: # too much recursion # - /proc/sys is still there, unless you want to hit that charming error: # FATAL: error reading `/proc/sys/crypto/fips_enabled' in libgcrypt: Not a directory proc_options="" # - /dev is present yet minimalist # /dev/dri is included for the sake of webGL performance and to avoid the # following error message: # libGL error: failed to open drm device: No such file or directory dev_options=" --bind=${dev_dir}:/dev --bind=/dev/dri:/dev/dri --bind=/dev/null:/dev/null --bind=/dev/random:/dev/random --bind=/dev/urandom:/dev/urandom" # Let users override this through "configuration files": generic_config_path="${HOME}/.config/browser-wrapper/main.conf" [ -f "${generic_config_path}" ] && source "${generic_config_path}" specific_config_path="${HOME}/.config/browser-wrapper/${invoked_name}.conf" [ -f "${specific_config_path}" ] && source "${specific_config_path}" # Let users override some things through environment variables: [ -n "${BW_PROOT_PATH}" ] && proot_path="${BW_PROOT_PATH}" [ -n "${BW_BROWSER_PATH}" ] && browser_path="${BW_BROWSER_PATH}" if [ -x "${proot_path}" ]; then echo "proot is present and will be used to mask some directories" echo 'Tips:' echo " Your fake home is ${home_dir}" echo " Your fake /tmp is ${tmp_dir}" echo ' Do you need to upload files?' echo " Put them in ${upload_dir}" echo ' Do you need to download files?' echo " They should end up in ${download_dir}" "${proot_path}" \ ${pre_options} \ ${root_dir_options} \ ${slash_home_options} \ ${home_options} \ ${browser_conf_options} \ ${download_options} \ ${upload_options} \ ${adobe_options} \ ${java_options} \ ${tmp_options} \ ${sys_options} \ ${proc_options} \ ${dev_options} \ ${post_options} \ --cwd="${HOME}" \ "${browser_path}" "$@" else echo "proot is missing; the browser will NOT be launched" exit 127 fi