sandboxes.am 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #!/bin/sh
  2. ###################################################################################################
  3. # THIS MODULE INCLUDES ALL ACTIONS INTENDED TO ISOLATE DOTFILES OR CONTAINERIZE INSTALLED APPIMAGES
  4. ###################################################################################################
  5. # Get xdg variables for _configure_dirs_access
  6. for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do
  7. eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)"
  8. [ "$XDG_DIR" = "$HOME" ] || [ "$XDG_DIR" = "$HOME/" ] && XDG_DIR=""
  9. eval $DIR="$XDG_DIR"
  10. done
  11. DESKTOP="$(echo "${DESKTOP:-~/Desktop}" | sed "s|$HOME|~|g")"
  12. DOCUMENTS="$(echo "${DOCUMENTS:-~/Documents}" | sed "s|$HOME|~|g")"
  13. DOWNLOAD="$(echo "${DOWNLOAD:-~/Downloads}" | sed "s|$HOME|~|g")"
  14. GAMES="$(echo "${GAMES:-~/Games}" | sed "s|$HOME|~|g")"
  15. MUSIC="$(echo "${MUSIC:-~/Music}" | sed "s|$HOME|~|g")"
  16. PICTURES="$(echo "${PICTURES:-~/Pictures}" | sed "s|$HOME|~|g")"
  17. VIDEOS="$(echo "${VIDEOS:-~/Videos}" | sed "s|$HOME|~|g")"
  18. _check_appimage() {
  19. _determine_args
  20. TARGET="$(command -v "$1")"
  21. APPIMAGEDIR=$(echo "$ARGPATHS" | grep "/$1$")
  22. APPIMAGE="$APPIMAGEDIR/$1"
  23. if [ ! -d "$APPIMAGEDIR" ]; then
  24. echo " ERROR: \"$1\" is not installed"
  25. return 1
  26. elif ! strings -d "$APPIMAGE" | grep -- '--appimage-extract' 1>/dev/null; then
  27. echo " ERROR: \"$1\" is NOT an AppImage"
  28. return 1
  29. fi
  30. }
  31. _home() {
  32. if [ -d "$APPIMAGE.home" ]; then
  33. echo " ERROR: \"$1\" already contains a home dir"
  34. return 1
  35. fi
  36. mkdir "$APPIMAGE.home" || return 1
  37. echo " \$HOME set to \"$APPIMAGE.home\" for \"$1\""
  38. }
  39. _config() {
  40. if [ -d "$APPIMAGE.config" ]; then
  41. echo " ERROR: \"$1\" already contains a config dir"
  42. return 1
  43. fi
  44. mkdir "$APPIMAGE.config" || return 1
  45. echo " \$XDG_CONFIG_HOME set to \"$APPIMAGE.config\" for \"$1\""
  46. }
  47. _disable_sandbox() {
  48. TARGET="$(command -v "$1")"
  49. if ! grep "aisap-am sandboxing script" "$TARGET" >/dev/null 2>&1; then
  50. echo " ERROR: Not a sandboxed AppImage, aborting"
  51. return 1
  52. fi
  53. "$1" --disable-sandbox
  54. }
  55. _check_aisap() {
  56. if [ "$1" = "aisap" ]; then
  57. echo " Error: You can't sandbox aisap"
  58. return 1
  59. elif ! command -v aisap 1>/dev/null; then
  60. printf '\n%s\n\n' " Error: You need aisap for this script work"
  61. read -r -p " ◆ DO YOU WISH TO INSTALL AISAP? Install size <5 MiB? (Y/n) " yn
  62. if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
  63. echo " OPERATION ABORTED!"
  64. return 1
  65. fi
  66. "$AMCLIPATH" -i aisap >/dev/null 2>&1
  67. command -v aisap 1>/dev/null || return 1
  68. echo " aisap installed successfully!"
  69. fi
  70. if grep "aisap-am" "$TARGET" >/dev/null 2>&1; then
  71. echo " $1 is already sandboxed!"
  72. return 1
  73. fi
  74. }
  75. _generate_sandbox_script() {
  76. echo "$DIVIDING_LINE"
  77. printf '\n%s\n' " Making aisap sandbox script for \"$1\"..."
  78. tmpscript="$(cat <<-'HEREDOC'
  79. #!/bin/sh
  80. # aisap-am sandboxing script, aisap: https://github.com/mgord9518/aisap
  81. # Thanks a lot to mgord9518 for making aisap!
  82. # Run this script with --disable-sandbox to do what the flag name implies
  83. # The default location for the sandboxed home is in $HOME/.local/am-sandboxes
  84. # But that location can be changed by setting the $SANDBOXDIR env variable
  85. # Dependency check
  86. if ! command -v aisap 1>/dev/null; then
  87. echo "You need aisap for this to work"
  88. notify-send -u critical "Sandbox error: Missing aisap dependency!"
  89. exit 1
  90. fi
  91. # Set variables and create sandboxed dir.
  92. APPEXEC=DUMMY
  93. chmod a-x "$APPEXEC" # Prevents accidental launch of app outside the sandbox
  94. APPNAME="$(echo "$APPEXEC" | awk -F "/" '{print $NF}')"
  95. SANDBOXDIR="${SANDBOXDIR:-$HOME/.local/am-sandboxes}"
  96. DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}"
  97. CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}"
  98. CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}"
  99. DBUS="$(ls /tmp/dbus* 2>/dev/null | head -1)"
  100. # get xdg user dirs, unset if var = $HOME
  101. for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do
  102. eval XDG_DIR="$(xdg-user-dir $DIR 2>/dev/null)"
  103. [ "$XDG_DIR" = "$HOME" ] || [ "$XDG_DIR" = "$HOME/" ] && XDG_DIR=""
  104. eval $DIR="$XDG_DIR"
  105. done
  106. # Use default location if var is not set
  107. DESKTOP="${DESKTOP:-~/Desktop}"
  108. DOCUMENTS="${DOCUMENTS:-~/Documents}"
  109. DOWNLOAD="${DOWNLOAD:-~/Downloads}"
  110. GAMES="${GAMES:-~/Games}"
  111. MUSIC="${MUSIC:-~/Music}"
  112. PICTURES="${PICTURES:-~/Pictures}"
  113. VIDEOS="${VIDEOS:-~/Videos}"
  114. # Try find the right name of the app conf/data dir
  115. APPDATA=$( ls "$DATADIR" | grep -i "$APPNAME" | head -1 )
  116. APPCONF=$( ls "$CONFIGDIR" | grep -i "$APPNAME" | head -1 )
  117. # Disable sandbox
  118. if [ "$1" = "--disable-sandbox" ]; then
  119. APPIMAGEDIR="${APPEXEC%/*}"
  120. echo ""
  121. echo " Giving exec permissions back to $APPEXEC..."
  122. chmod a+x "$APPEXEC" || exit 1
  123. echo " Patching $APPIMAGEDIR/AM-updater to give permissions back..."
  124. sed -i 's|chmod a-x|chmod a+x|g' "$APPIMAGEDIR/AM-updater" || exit 1
  125. THISFILE="$(realpath "$0")"
  126. echo " Replacing $THISFILE with a link to the AppImage..."
  127. SUDO ln -sf "$APPEXEC" "$THISFILE" || exit 1
  128. printf '\033[32m\n%s\n\033[0m\n' " $APPEXEC successfully unsandboxed!"
  129. exit 0
  130. fi
  131. mkdir -p "$SANDBOXDIR/$APPNAME"
  132. [ -z "$APPNAME" ] && exit 1
  133. # Start at sandboxed home
  134. # Edit below this to add or remove access to parts of the system
  135. exec aisap --trust-once --level 2 \
  136. --data-dir "$SANDBOXDIR/$APPNAME" \
  137. --add-file "$DATADIR/${APPDATA:-$APPNAME}":rw \
  138. --add-file "$DATADIR"/themes \
  139. --add-file "$DATADIR"/icons \
  140. --add-file "$CONFIGDIR/${APPCONF:-$APPNAME}":rw \
  141. --add-file "$CONFIGDIR"/dconf \
  142. --add-file "$CONFIGDIR"/gtk3.0 \
  143. --add-file "$CONFIGDIR"/gtk4.0 \
  144. --add-file "$CONFIGDIR"/kdeglobals \
  145. --add-file "$CONFIGDIR"/qt5ct \
  146. --add-file "$CONFIGDIR"/qt6ct \
  147. --add-file "$CONFIGDIR"/Kvantum \
  148. --add-file "$HOME"/.local/lib \
  149. --add-file /usr/share \
  150. --rm-file /NOPATH \
  151. --rm-file "$DESKTOP" \
  152. --rm-file "$DOCUMENTS" \
  153. --rm-file "$DOWNLOAD" \
  154. --rm-file "$GAMES" \
  155. --rm-file "$MUSIC" \
  156. --rm-file "$PICTURES" \
  157. --rm-file "$VIDEOS" \
  158. --add-file /var/lib/dbus \
  159. --add-file "${DBUS:-/tmp/dbus}" \
  160. --add-socket pulseaudio \
  161. --add-socket dbus \
  162. --add-socket network \
  163. --add-socket x11 \
  164. --add-socket wayland \
  165. --add-device dri -- \
  166. "$APPEXEC" "$@"
  167. HEREDOC
  168. )"
  169. }
  170. _configure_dirs_access() {
  171. printf '\033[33m\n'
  172. read -r -p " Do you want configure access to directories? (Y/n): " yn
  173. if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
  174. return 0
  175. fi
  176. printf '\033[36m'
  177. for DIR in DESKTOP DOCUMENTS DOWNLOAD GAMES MUSIC PICTURES VIDEOS; do
  178. eval XDG_DIR=\$$DIR
  179. read -r -p " Allow $1 access to \"$XDG_DIR\"? (y/N) " yn
  180. if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
  181. tmpscript=$(echo "$tmpscript" \
  182. | sed "s#--rm-file \"\$$DIR\"#--add-file \"\$$DIR\":rw#g" )
  183. fi
  184. done
  185. sleep 0.5
  186. printf '\033[31m'
  187. read -r -p " Allow $1 access to a specific directory? (y/N) " yn
  188. if echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
  189. echo " WARNING: Giving access to all of $HOME or / and similar is not safe"
  190. echo " Also aisap might not let $1 start when such paths are given"
  191. printf '\033[33m%s\n' " Type the path to the directory"
  192. read -r -p " Example: /media/external-drive or ~/Backups: " NEWDIR
  193. case "$NEWDIR" in
  194. '$HOME'|'$HOME/'|"$HOME"|"$HOME/"|"/"|"~"|"~/"|"/home"|"/home/"|\
  195. "$DATADIR"|'$XDG_DATA_HOME'|"$CONFIGDIR"|'$XDG_CONFIG_HOME'|"$BINDIR")
  196. notify-send -u critical "DO YOU WANT THE FBI TO GET YA?"
  197. printf '\033[31m\n'
  198. read -r -p " SPOOKY LOCATION! ARE YOU SURE? IF SO TYPE \"YES\": " YES
  199. [ "$YES" != "YES" ] && echo " That's not \"YES\", aborting" && return 1
  200. ;;
  201. '')
  202. printf '\033[31m\n%s\n\n' " No path given, aborting"
  203. return 1
  204. ;;
  205. esac
  206. echo " Giving access to \"$NEWDIR\"..."
  207. tmpscript=$(echo "$tmpscript" \
  208. | sed "s#--rm-file /NOPATH#--add-file \"$NEWDIR\":rw#g")
  209. fi
  210. printf '\n\033[32m%s\n' " User directories access configured successfully!"
  211. }
  212. _install_sandbox_script() {
  213. tmpscript=$(echo "$tmpscript" | sed "s#DUMMY#$APPIMAGE#g; s#SUDO#$SUDOCMD#g")
  214. # Remove exec permission from AppImage and its updater for better safety™
  215. chmod a-x "$APPIMAGE" || return 1
  216. sed -i 's|chmod a+x|chmod a-x|g' "$APPIMAGEDIR/AM-updater" || return 1
  217. # Install the script
  218. $SUDOCMD rm -f "$TARGET" || return 1
  219. echo "$tmpscript" | $SUDOCMD tee "$TARGET" >/dev/null 2>&1 || return 1
  220. $SUDOCMD chmod a+x "$TARGET"
  221. SANDBOXDIR="${SANDBOXDIR:-$HOME/.local/am-sandboxes}"
  222. printf '\033[32m\n%s\n\033[0m' " \"$1\" successfully sandboxed!"
  223. printf '\n%s\n' " $1 will be sandboxed in \"$SANDBOXDIR\""
  224. printf '%s\n\n' " once launched"
  225. printf '%s\n' " Set the \$SANDBOXDIR env variable to move the location"
  226. printf '\n%s' ' Use '
  227. printf '\033[33m%s' '--disable-sandbox'
  228. printf '\033[0m%s\033[33m\n' " to revert the changes, in this case that is:"
  229. printf '\033[33m%s\033[0m' " $1 --disable-sandbox"
  230. printf '%s\033[33m%s\n\033[0m\n' " or " "$AMCLI --disable-sandbox $1"
  231. }
  232. # Main logic
  233. [ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
  234. case "$1" in
  235. '--sandbox')
  236. shift
  237. while [ "$#" -gt 0 ]; do
  238. _check_appimage "${@}" && _check_aisap "${@}" \
  239. && _generate_sandbox_script "${@}" \
  240. && _configure_dirs_access "${@}" \
  241. && _install_sandbox_script "${@}"
  242. shift
  243. done
  244. ;;
  245. '--disable-sandbox')
  246. shift
  247. while [ "$#" -gt 0 ]; do
  248. echo "$DIVIDING_LINE"
  249. _disable_sandbox "${@}"
  250. shift
  251. done
  252. ;;
  253. '-H'|'--home')
  254. shift
  255. while [ "$#" -gt 0 ]; do
  256. _check_appimage "${@}" && _home "${@}"
  257. shift
  258. done
  259. ;;
  260. '-C'|'--config')
  261. shift
  262. while [ "$#" -gt 0 ]; do
  263. _check_appimage "${@}" && _config "${@}"
  264. shift
  265. done
  266. ;;
  267. esac
  268. _remove_info_files