Top Banner
#!/bin/bash # Script Name: sandfox http://igurublog.wordpress.com/downloads/script-sandfox/ # Requires: inotify-tools # License: GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.txt help () { cat << EOF sandfox version 1.1.4 Usage: sandfox [OPTIONS] [COMMAND [ARG]...] Runs COMMAND as a normal user within a chroot jail sandbox with limited access to the filesystem. Supports profiles for apps and includes a default Firefox profile. Must be run as root when creating sandbox. Examples: sudo sandfox firefox # Runs Firefox in a sandbox sudo sandfox bash # Shell to explore a sandbox OPTIONS: --bindro TARGET Include TARGET (a file or folder) in the sandbox bind-mounting it as a read-only filesystem --bind TARGET Include TARGET (a file or folder) in the sandbox with same ownership and permissions when possible --copy TARGET Place a disposable copy of TARGET (a file or folder) in the sandbox --hide TARGET Include TARGET (a file or folder) in the sandbox by bind-mounting an empty file or folder onto it Effectively hides the real TARGET from the sandbox Also provides a writable dummy folder --profile PROFILE Load PROFILE (a profile name or pathname). By default profiles are stored in $defaultprofolder --make Force creation or update of a sandbox (make is implied if you specify binds or profiles) --sandbox NAME Specify name of sandbox to use, create, or update --close NAME Unmount and remove sandbox NAME --closeall Unmount and remove ALL sandboxes --status Show the status of all current sandboxes --shell Run COMMAND in a shell and wait. Requires root. (bash is always run in a shell) --user USERNAME Run command as USER in the sandbox - useful if auto-detection does not work or to override --profilefolder FOLDER Use FOLDER instead of the default profile folder IMPORTANT: should be root owned & write- protected --logfile LOGFILE Also append messages to LOGFILE. sandfox daemons will also update this file provided it is accessible from within the sandbox. --verbose Provide detailed feedback
29

Sobre los secretos de la vida

Sep 11, 2015

Download

Documents

Javier López

Sobre lo absurdo del sistema de recompensa en este sitio.

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • #!/bin/bash # Script Name: sandfox http://igurublog.wordpress.com/downloads/script-sandfox/ # Requires: inotify-tools # License: GNU GENERAL PUBLIC LICENSE Version 3 http://www.gnu.org/licenses/gpl-3.0.txt help () { cat
  • --quiet Minimize output messages NOTES: OPTIONS must precede COMMAND; you can also use OPTION=VALUE; binds are processed in this order: bindro bind copy hide; missing binds are ignored; if a profile for COMMAND exists it will be automatically loaded; default profile is always loaded; profiles may contain any options valid on the command line; if COMMAND is omitted, a sandbox will be created for use. Instructions and updates: http://igurublog.wordpress.com/downloads/script-sandfox/ EOF exit 0 } log () { output=0 if (( optquiet == 1 )) && [ "$2" = "quiet" ]; then output=1 elif (( optverbose == 1 )) && [ "$2" = "verb" ]; then output=1 elif (( optquiet == 0 )) && [ "$2" != "verb" ]; then output=1 fi if (( output == 1 )); then if (( optdaemon == 1 )); then d="sandfox-daemon($(basename "${watchs[0]}")): " else d="" fi echo "$1" if [ "$logfile" != "" ]; then echo "$(date '+%Y-%m-%d %H:%M:%S'): $d$1" >> "$logfile" fi fi } processopt () { # $1 $2 # Process a command line or profile option opt="$1" opt2="$2" shifts=2 if [ "${opt:0:2}" = "--" ]; then opt="${opt:2}" fi case "$opt" in help | -help | -h ) help exit ;; bind | bindrw | bindro | hide | copy | watch ) if [ "${opt2:0:1}" != "/" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires an absolute path" "quiet" exit 1 fi if [ "$opt" = "bindrw" ]; then

  • opt="bind" fi eval $opt\s[\$$opt\scnt]=\"\$opt2\" eval \(\( $opt\scnt += 1 \)\) ;; profile ) if [ "${opt2:0:1}" = "-" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires a profile name or file" "quiet" exit 1 fi prof[$profcnt]="$opt2" (( profcnt += 1 )) ;; profilefolder ) if [ "$profolder" != "" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Multiple profile folders not permitted" "quiet" exit 1 elif [ "${opt2:0:1}" != "/" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires an absolute path" "quiet" exit 1 fi profolder="$opt2" ;; sandbox ) if [ "$sandbox" != "" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Multiple sandbox names not permitted" "quiet" exit 1 fi opt2base=`basename "$opt2"` if [ "${opt2:0:1}" = "-" ] || [ "$opt2" = "" ] || [ "$opt2" != "$opt2base" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires a sandbox name" "quiet" exit 1 fi sandbox="$opt2" ;; close ) opt2base=`basename "$opt2"` if [ "${opt2:0:1}" = "-" ] || [ "$opt2" = "" ] || [ "$opt2" != "$opt2base" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires a sandbox name" "quiet" exit 1 fi closename[$closecnt]="$2" (( closecnt += 1 )) ;; logfile ) if [ "${opt2:0:1}" != "/" ]; then

  • log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires an absolute path" "quiet" exit 1 fi if [ "$logfile" != "" ]; then log "$curprofile: Warning: Multiple log files ignored" "quiet" else logfile="$opt2" if (( optdaemon == 0 )); then echo "=======================================================================" >> "$logfile" echo "sandfox started $(date +%Y-%m-%d' '%H:%M:%S) on $HOSTNAME" >> "$logfile" echo "$logcl" >> "$logfile" else log "Started >>> $logcl" fi chmod go+rw "$logfile" 2> /dev/null fi ;; make | verbose | quiet | keepsand | clean | closeall | status | daemon | shell ) eval opt$opt=1 if (( optquiet + optverbose == 2 )); then optquiet=0 fi shifts=1 ;; user ) if [ "${opt2:0:1}" = "-" ]; then log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Option $opt requires a username" "quiet" exit 1 fi if [ "$curprofile" = "commandline" ]; then user="$opt2" else log "$curprofile: Warning: Option $opt ignored in profile" fi ;; * ) log "$curprofile: Option $opt $opt2" "verb" log "$curprofile: Error: Unknown option $opt" "quiet" exit 1 ;; esac if (( shifts == 2 )); then log "$curprofile: Option $opt $opt2" "verb" else log "$curprofile: Option $opt" "verb" fi return $shifts } loadprofile () { # $1=profile name or path

  • p="$1" # exists? if [ "${p:0:1}" != "/" ]; then test1=`basename "$p"` test2=`basename "$p" "profile"` if [ "$test1" = "$test2" ]; then p="$profolder/$p.profile" else p="$profolder/$p" fi fi if [ ! -e "$p" ]; then log "sandfox: Error: Missing profile $p" "quiet" exit 3 fi # already loaded? loadedprofidx=0 load=1 while (( loadedprofidx < loadedprofcnt )); do if [ "$p" = "${loadedprof[$loadedprofidx]}" ]; then load=0 break fi (( loadedprofidx += 1 )) done if (( load == 1 )); then curprofile="$p" # global var loadedprof[$loadedprofcnt]="$p" (( loadedprofcnt += 1 )) # read profile log "Loading profile \"$1\"" IFS=$'\n' loadedopts=`grep -v -e "^[[:blank:]]*#" "$p"` for l in $loadedopts ; do lorg="$l" if [ "$l" != "" ]; then l2=${l#*=} if [ "$l" != "$l2" ]; then # split = into two opts l=${l%%=*} else l2="" fi # remove whitespace and comments while [[ $"${l:0:1}" =~ [[:blank:]] ]]; do l="${l:1}" done l=${l%%#*} lenl=${#l} (( lenl -= 1 )) while [[ $"${l:lenl:1}" =~ [[:blank:]] ]]; do l="${l:0:lenl}" lenl=${#l} (( lenl -= 1 )) done l=${l%%[[:blank:]]} while [[ $"${l2:0:1}" =~ [[:blank:]] ]]; do l2="${l2:1}" done l2=${l2%%#*}

  • lenl2=${#l2} (( lenl2 -= 1 )) while [[ $"${l2:lenl2:1}" =~ [[:blank:]] ]]; do l2="${l2:0:lenl2}" lenl2=${#l2} (( lenl2 -= 1 )) done # process if [ "$l" != "" ]; then processopt "$l" "$l2" elif [ "$l2" != "" ]; then log "sandfox: Syntax error in profile $p" "quiet" log " Line: $lorg" "quiet" exit 3 fi fi done IFS=" " fi } randhex4() # generate a four digit random hex number { rand1=$RANDOM rand2=$RANDOM (( rand = rand1 + rand2 )) let "rand %= 65536" randhex=`printf "%04X" $rand | tr A-Z a-z` if [ "$randhex" = "" ]; then randhex=$RANDOM # failsafe fi } rmbox () { # $1=mnt folder to remove if [ "$1" = "" ]; then return elif [ ! -d "$1" ]; then return fi cleanpath="$1" IFS=$'\n' # find dbus daemon(s) running in sandbox(s) # If DBUS_SESSION_BUS_ADDRESS is not provided, firefox will # launch a dbus session inside the sandbox. This needs to be killed # for the sandbox to be closed. if [ "$cleanpath" != "$mnt" ]; then # single sandbox dbuspids=`lsof -w 2> /dev/null | grep $cleanpath/usr/bin/dbus-launch$ | awk '{print $2}'` else # all sandboxes dbuspids=`lsof -w 2> /dev/null | grep $cleanpath/.*/usr/bin/dbus-launch$ | awk '{print $2}'` fi # kill dbus-launch in sandbox(s) for dpid in $dbuspids ; do log ">>> kill $dpid # kill dbus-launch in sandbox" "verb" kill $dpid sleep 1

  • tries=0 while (( tries < 20 )) && [ "$(ps -o pid= -p $dpid)" != "" ]; do if (( tries == 0 )); then log "Waiting for dbus-launch ($dpid) to terminate..." fi sleep .5 (( tries++ )) done done # get mount points in reverse order mname="$cleanpath" mname=${mname//\//\\\/} # convert slashes mtab=`mount | grep " on $cleanpath\/" | sed "s/.* on \($mname.*\) type .*/\1/" | tac` if [ "$mtab" != "" ]; then # umount in reverse order for m in $mtab ; do log ">>> umount \"$m\"" "verb" test=`umount "$m" 2>&1` if [ "$?" != "0" ]; then log "$test" log "sandfox: Error: Closure incomplete - mounts may still exist on" "quiet" log " $cleanpath Close programs running in" "quiet" log " the sandbox and try again. If problem persists see output of:" "quiet" log " lsof -w | grep $cleanpath" exit 4 fi done # do safety checks then remove folder mounts=`mount | grep " on $cleanpath\/" | sed "s/.* on \($mname.*\) type .*/\1/"` f1=`find "$cleanpath" -xdev -type f | wc -l 2> /dev/null` f2=`find "$cleanpath" -type f | wc -l 2> /dev/null` if [ "$f1" != "$f2" ] && [ "$mounts" = "" ]; then log "sandfox: Error: Not all files could be safely removed from $cleanpath" "quiet" log " This may indicate a hidden bind mount still exists. It is" "quiet" log " recommended that you reboot or backup original folders, then" "quiet" log " manually remove $cleanpath as root." "quiet" exit 4 elif (( f1 > 50 )) && [ "$mounts" = "" ]; then log "sandfox: Error: Not all files could be safely removed from $cleanpath" "quiet" log " because the number of files remaining exceeds the safety limit" "quiet" log " of 50. It is recommended that you reboot or backup original" "quiet" log " folders, then manually remove $cleanpath as root." "quiet" exit 4 elif [ "$mounts" != "" ]; then log "sandfox: Error: Closure incomplete - mounts still exist on" "quiet" log " $cleanpath Close programs running in" "quiet"

  • log " the sandbox and try again. Mounts:" "quiet" log "$mounts" "quiet" exit 4 else log "Removing $cleanpath" "verb" log ">>> find \"$cleanpath\" -xdev | sort -r" "verb" f1=`find "$cleanpath" -xdev | sort -r 2> /dev/null` if [ "$f1" != "" ]; then for f in $f1 ; do if [ -d "$f" ]; then rmdir "$f" else rm "$f" fi done fi if [ -e "$cleanpath" ]; then log "sandfox: Error: Not all files could be safely removed from $cleanpath" "quiet" log " This may indicate a hidden bind mount. It is recommended" "quiet" log " that you reboot or backup original folders before" "quiet" log " manually removing $cleanpath as root." "quiet" exit 4 fi fi fi IFS=" " } mkmount () { # $1=original folder # make mount point odir="$1" fdir="$sand$1" mkdir -p "$fdir" 2> /dev/null # recursively copy original folder ownership & permissions while [ "$odir" != "" ]; do if [ -e "$odir" ]; then chmod --reference="$odir" "$fdir" 2> /dev/null chown --reference="$odir" "$fdir" 2> /dev/null else chmod ugo+rwx "$fdir" 2> /dev/null chown $user:$user "$fdir" 2> /dev/null fi odir=${odir%/*} fdir=${fdir%/*} done } sandmount () { # $1=type $2=source $3=target case "$1" in bind | bindro ) if [ -d "$2" ]; then mkmount "$2" elif [ ! -e "$3" ]; then mdir=`dirname "$2"` mkmount "$mdir" touch "$3"

  • fi log ">>> mount --bind \"$2\" \"$3\"" "verb" mount --bind "$2" "$3" merr1=$? if [ "$2" != "/dev/random" ] && [ "$2" != "/dev/urandom" ]; then # remount if [ "$1" = "bindro" ]; then if [ "$2" = "/tmp" ]; then log "sandfox: Warning: You are mounting /tmp read-only - your programs" log " may not work properly in this sandbox" fi mopt="remount,bind,noatime,nosuid,ro" else mopt="remount,bind,noatime,nosuid" fi log ">>> mount -o $mopt \"$3\"" "verb" mount -o $mopt "$3" merr2=$? else # don't remount /dev/random - causes hang merr2=0 if [ "$1" = "bindro" ]; then log "sandfox: Warning: $2 cannot be mounted ro - mounted rw" fi fi test=`mount | grep " on $3 type "` if [ "$test" = "" ] || (( merr1 + merr2 != 0 )); then log "sandfox: Error: $1 mount failed on $3" "quiet" if (( newsand == 1 )); then rmbox "$sand" fi exit 4 fi ;; tmpfs ) mkmount "$2" if [ -d "$3" ]; then log ">>> mount -t tmpfs -o noatime,nosuid,size=$tmpfslimit tmpfs \"$3\"" "verb" mount -t tmpfs -o noatime,nosuid,size=$tmpfslimit tmpfs "$3" merr1=$? test=`mount | grep "^tmpfs on $3 type tmpfs"` if [ "$test" = "" ] || (( merr1 != 0 )); then log "sandfox: Error: tmpfs mount failed on $3" "quiet" if (( newsand == 1 )); then rmbox "$sand" fi exit 4 fi else log "sandfox: Warning: Could not hide $2" fi ;; esac

  • } boxstatus () { # $1 =box name OR "" for all if [ "$1" = "" ]; then boxes=`find $mnt -maxdepth 1 -mindepth 1 -type d 2> /dev/null` else boxes="$1" fi IFS=$'\n' log if [ "$boxes" = "" ]; then log " No sandboxes exist" else for b in $boxes ; do bname="$(basename "$b")" testdaemons=`ps -eo user,cmd | grep -v -e "grep" -e " /bin/su " | grep -c "sandfox .*--daemon.*$eventsfolder/$bname[[:blank:]]*$"` testfolders=`find "$b" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort` testfolders="${testfolders//$IFS/ }" testmounts=`mount | grep -c " on $b/"` if [ "$testfolders" != "" ] || [ "$testdaemons" != "" ] || (( testmounts > 0 )); then makemsg=" (remake this sandbox to use it)" if (( testdaemons < 1 )) || [ ! -d "$eventsfolder/$bname" ]; then testdaemons="disabled$makemsg" makemsg="" else testuser=`ps -eo "%U %a" | grep -v -e "grep" -e " /bin/su " \ | grep -m 1 "sandfox .*--daemon.*$eventsfolder/$bname[[:blank:]]*$" \ | sed 's/\([a-zA-Z0-9]*\) .*/\1/'` testdaemons="running ($testuser)" fi if (( testmounts < 1 )); then testmounts="none$makemsg" makemsg="" else testmounts="$testmounts $mnt/$bname/" fi if [ testfolders = "" ]; then testfolders="none$makemsg" fi log "Sandbox: $bname" log " Daemon: $testdaemons" log " Mounts: $testmounts" log " Root Dirs: $testfolders" log fi done fi IFS=" " } mkprofiles () { # profile folder if [ "$profolder" = "" ]; then profolder="$defaultprofolder"

  • fi mkdir -p "$profolder" if [ ! -d "$profolder" ]; then log "sandfox: Error: Could not create profile folder $profolder" "quiet" exit 3 fi if [ ! -e "$profolder/default.profile" ]; then cat "$profolder/default.profile" # Sandfox Default Profile # # WARNING: This default profile is loaded for all sandboxes and should only # contain the minimum folders required by all apps. If you do not at # least bind /bin /lib and /etc then the chroot command may not succeed. # # For instructions consult http://igurublog.wordpress.com/downloads/script-sandfox/ # OPTION # or # OPTION=VALUE (Do not use quotes) # # To include another profile in this profile: # profile=PROFILENAME # root folders and files bindro=/bin # required by chroot su - do not remove bindro=/etc # required by chroot su - do not remove bindro=/lib # required by chroot su - do not remove # recommended to keep apps happy bind=/dev/null bind=/dev/urandom bind=/dev/random bind=/dev/nvidia0 bind=/dev/nvidiactl bindro=/lib32 bindro=/lib64 bindro=/opt/lib32 bind=/tmp bindro=/usr bindro=/var/lib hide=/var/lib/mlocate # security # home folders and files # probably better to bind most home folders and files in another profile copy=/home/\$user/.bashrc # provides a disposable copy copy=/home/\$user/.bash_profile # provides a disposable copy # other folders and files # probably better to put these in another profile

  • # Lockdown X Access (experimental) # These hides, disabled by default, MAY HELP to lockdown X access - for # example to discourage sandboxed apps from taking screen snapshots or # doing keylogging. If you enable these, be sure to close all sandboxes # before updating your system. Your package manager won't be able to # update these files while they are mounted in a sandbox. # # hide=/usr/bin/import # hide=/usr/bin/xauth # hide=/usr/bin/xev # hide=/usr/bin/xhost # hide=/usr/bin/xwd # hide=/usr/bin/xscreensaver # hide=/usr/bin/xscreensaver-command # hide=/usr/bin/xscreensaver-demo # hide=/usr/bin/xscreensaver-getimage # hide=/usr/bin/xscreensaver-getimage-file # hide=/usr/bin/xscreensaver-getimage-video # hide=/usr/bin/Xorg # hide=/etc/X11 # hide=/usr/lib/X11 EOF fi if [ ! -e "$profolder/firefox.profile" ]; then cat "$profolder/firefox.profile" # Sandfox Firefox Profile # # Note that default.profile is always loaded in addition to other profiles # # For instructions consult http://igurublog.wordpress.com/downloads/script-sandfox/ # OPTION # or # OPTION=VALUE (Do not use quotes) # # To include another profile in this profile: # profile=PROFILENAME # root folders and files required by firefox bindro=/bin bindro=/opt/firefox # sometimes firefox is installed here bind=/dev/null bind=/dev/urandom # used by Firefox for security purposes bind=/dev/random # used by Firefox for printing bind=/dev/nvidia0 bind=/dev/nvidiactl bindro=/etc bindro=/lib bindro=/lib32 bindro=/lib64 bindro=/opt/lib32 bind=/tmp bindro=/usr bindro=/var/lib hide=/var/lib/mlocate bindro=/run/resolvconf # used by Firefox for DNS support

  • # required by alsa for Flash sound bindro=/dev/snd # required by Java bindro=/opt/java bindro=/proc # required by Cups printing in Firefox bind=/var/cache/cups # Firefox starts faster bind=/var/cache/fontconfig # Firefox starts faster bind=/var/run # Firefox shows Cups printers # home folders and files # You may need to add additional binds to your home folders and files in order # for every aspect of Firefox to work as you want. Or you can share your # entire /home/\$user folder (this would reduce security) bind=/home/\$user/.mozilla bind=/home/\$user/.esd_auth bind=/home/\$user/.java bindro=/home/\$user/.asoundrc # Needed for KDE and Gnome themes in Firefox (may be incomplete for gnome) # To find out what other binds you may need, run 'env' in a shell as user # and examine the values of GTK2_RC_FILES and GTK_RC_FILES and XCURSOR_THEME # Note: The bind for kdeglobals below is a limited privacy risk, as KDE4 stores # recent file and folder names in this file. You can clean this file with # kscrubber: http://igurublog.wordpress.com/downloads/script-kscrubber/ # or don't bind it, but your theme may not work in Firefox bind=/home/\$user/.config/gtk-2.0 bindro=/home/\$user/.fontconfig bindro=/home/\$user/.fonts bind=/home/\$user/.gtkrc-2.0 bind=/home/\$user/.gtkrc-2.0-kde4 bind=/home/\$user/.kde/share/config/gtkrc bind=/home/\$user/.kde/share/config/gtkrc-2.0 bindro=/home/\$user/.kde/share/config/kdeglobals bind=/home/\$user/.kde4/share/config/gtkrc bind=/home/\$user/.kde4/share/config/gtkrc-2.0 bindro=/home/\$user/.kde4/share/config/kdeglobals bindro=/home/\$user/.gtkrc-2.0-kde bind=/home/\$user/.kde3/share/config/gtkrc bind=/home/\$user/.kde3/share/config/gtkrc-2.0 bindro=/home/\$user/.kde3/share/config/kdeglobals bindro=/home/\$user/.Xdefaults # for cursor theme bindro=/home/\$user/.Xauthority #bindro=/etc/gtk-2.0/gtkrc # used but already binded all of /etc # Required by flash player for persisent LSOs # Hide will store the cookies in ram and destroy them on exit. If you need # LSOs to be permanent, use bind= instead.

  • # http://www.wired.com/epicenter/2009/08/you-deleted-your-cookies-think-again/ hide=/home/\$user/.adobe # creates a dummy folder hide=/home/\$user/.macromedia # creates a dummy folder # other folders and files # You may want to bind your Downloads or other data folders below so you # can easily save and upload files from within Firefox. EOF fi if [ ! -e "$profolder/skype.profile" ]; then cat "$profolder/skype.profile" # Sandfox Skype Profile # # Note that default.profile is always loaded in addition to other profiles # # For instructions consult http://igurublog.wordpress.com/downloads/script-sandfox/ # OPTION # or # OPTION=VALUE (Do not use quotes) # # To include another profile in this profile: # profile=PROFILENAME # Set this to your Skype video device # Note: /dev/video probably won't work bind=/dev/video0 bind=/dev/shm bind=/dev/snd bind=/dev/nvidia0 bind=/dev/nvidiactl # bind=/sys/devices/system/cpu # ??? # bindro=/etc/pulse/client.conf # only needed if /etc not bound bindro=/proc/interrupts bindro=/var/cache/libx11/compose bind=/tmp bindro=/usr bind=/usr/share/skype # Gentoo users may need to disable this bind bind=/opt/skype # Following only needed if all of /tmp not bound above # copy=/tmp/.ICE-unix # copy=/tmp/.X11-unix/X0 # bind=/tmp/pulse-*/native # Following only needed if all of /usr not bound above # copy=/usr/bin/skype # bindro=/usr/lib/qt4/plugins/iconengines # bindro=/usr/lib/qt4/plugins/imageformats # bindro=/usr/lib/qt4/plugins/imageformats # bindro=/usr/lib/qt4/plugins/inputmethods # bindro=/usr/share/X11/locale # bindro=/usr/share/icons # bindro=/usr/share/fonts

  • bind=/home/\$user/.Skype bindro=/home/\$user/.ICEauthority bindro=/home/\$user/.Xauthority bindro=/home/\$user/.config/Trolltech.conf bindro=/home/\$user/.fontconfig bindro=/home/\$user/.asoundrc EOF fi if [ ! -e "$profolder/google-earth.profile" ]; then cat "$profolder/google-earth.profile" # Sandfox Google-Earth Profile # # Note that default.profile is always loaded in addition to other profiles # # For instructions consult http://igurublog.wordpress.com/downloads/script-sandfox/ # OPTION # or # OPTION=VALUE (Do not use quotes) # # To include another profile in this profile: # profile=PROFILENAME # root folders and files bindro=/bin bind=/dev/null bind=/dev/urandom bind=/dev/random bind=/dev/nvidia0 bind=/dev/nvidiactl bindro=/etc bindro=/lib bindro=/lib32 bindro=/lib64 bindro=/opt/lib32 bind=/tmp bindro=/usr bindro=/var/lib hide=/var/lib/mlocate bindro=/opt/google/earth bindro=/opt/google-earth # required by Cups printing bind=/var/cache/cups bind=/var/cache/fontconfig bind=/var/run # home folders and files # You may need to add additional binds to your home folders and files in order # for every aspect of Google-Earth to work as you want. Or you can share your # entire /home/\$user folder (this would reduce security) bind=/home/\$user/.googleearth bind=/home/\$user/.config/Google bind=/home/\$user/.esd_auth bindro=/home/\$user/.config/Trolltech.conf

  • # Themes bindro=/home/\$user/.Xdefaults bindro=/home/\$user/.Xauthority bindro=/home/\$user/.fontconfig bindro=/home/\$user/.fonts # other folders and files # You may want to bind your Downloads or other data folders below so you # can easily save and upload files from within Google-Earth. EOF fi if [ ! -e "$profolder/default.profile" ] || \ [ ! -e "$profolder/firefox.profile" ] || \ [ ! -e "$profolder/google-earth.profile" ] || \ [ ! -e "$profolder/skype.profile" ]; then log "sandfox: Error: Could not create default profiles in $profolder" "quiet" exit 3 fi } ###################################################################################### # pre-init defaultprofolder="/etc/sandfox" # BE CAREFUL if you change $mnt - folder will be removed mnt="/mnt/sandfox" # eventsfolder cannot contain spaces and must be a bind eventsfolder="/tmp/sandfox-events" # maximum size of copy/hide folders tmpfslimit="100M" index=0 bindscnt=0 bindroscnt=0 hidescnt=0 copyscnt=0 watchscnt=0 closecnt=0 prof[0]="default" profcnt=1 profolder="" sandbox="" logfile="" logcl="$0 $*" curprofile="commandline" # find chroot wchroot=`which chroot` if [ "$wchroot" = "" ]; then if [ -e /usr/sbin/chroot ]; then wchroot=/usr/sbin/chroot elif [ -e /sbin/chroot ]; then wchroot=/sbin/chroot else wchroot=chroot fi

  • fi # parse command line if [ "$1" = "" ]; then help exit fi while [ "$1" != "" ]; do if [ "${1:0:1}" = "-" ]; then o2=${1#*=} if [ "$1" != "$o2" ]; then # split = into two opts o1=${1%%=*} noshift=1 else o1="$1" o2="$2" noshift=0 fi processopt "$o1" "$o2" if [ "$?" = "2" ] && (( noshift == 0 )); then shift fi else bcmd="$*" bprog="${bcmd%% *}" bprog="$(basename $bprog)" if [ "$bprog" = "" ]; then log "sandfox: Error: Could not determine sandbox program" "quiet" exit 1 fi break fi shift done # daemon mode # Note: Daemon mode is run internally as non-root user by sandfox to start # an events monitor which starts programs in the sandbox for the user # Daemon mode is not intended for direct use by the user if (( optdaemon == 1 )); then if (( watchscnt < 1 )); then log "sandfox-daemon: Error: Invalid daemon call - no watches" "quiet" exit 9 fi watchx=0 watchlist="" while (( watchx < watchscnt )); do watchlist="$watchlist \"${watchs[$watchx]}\"" (( watchx += 1 )) done # start watching user=`whoami` IFS=$'\n' while [ 1 ]; do

  • log ">>> inotifywait -eq modify $watchlist" "verb" fnotify=`eval /usr/bin/inotifywait -q -e modify -e moved_to -e create $watchlist` if [ "$?" != "0" ]; then log "Quitting - watch stopped" exit 0 fi # watch folders still exist? watchx=0 while (( watchx < watchscnt )); do if [ ! -d "${watchs[$watchx]}" ]; then log "Quitting - ${watchs[$watchx]} deleted" exit 0 fi (( watchx += 1 )) done # run f1=`echo "$fnotify" | grep -e " MODIFY " -e " CREATE " -e " MOVED_TO "` f1="${f1/ CREATE / MODIFY }" f1="${f1/ MOVED_TO / MODIFY }" if [ "$f1" != "" ]; then for fx in $f1 ; do fdir=${fx%% MODIFY *} f="$fdir${fx#* MODIFY }" ftest1=`basename "$f"` ftest2=`basename "$f" "desktop"` if [ "$ftest1" != "$ftest2" ]; then desktop=1 else desktop=0 fi if [ -f "$f" ] && [ -O "$f" ]; then if [ -x "$f" ] && (( desktop == 0)); then log "Executing $f..." $f & log "Deleting $f..." "verb" ( sleep 5 && rm -f "$f" ) & elif (( desktop == 1 )); then wcmd=`cat "$f" | grep -m 1 "^Exec="` if [ "$wcmd" != "" ]; then wcmd="${wcmd:5}" if [ "$wcmd" != "" ]; then log "Executing $wcmd ($f)..." eval $wcmd & log "Deleting $f..." "verb" ( sleep 5 && rm -f "$f" ) & else log "Could not execute $f" fi fi fi fi done fi done exit 12 fi # determine sandbox user

  • runuser=`whoami` if [ "$user" = "" ]; then if [ "$runuser" = "root" ]; then # based on env if [ "$SUDO_USER$LOGNAME$USER" != "" ]; then for u in $SUDO_USER $LOGNAME $USER ; do if [ "$u" != "root" ] && [ "$u" != "" ] && [ -e "/home/$u" ]; then user="$u" break fi done fi # based on Xauthority if [ "$user" = "" ] && [ "$XAUTHORITY" != "" ]; then user=`echo "$XAUTHORITY" | grep "^\/home\/.*\/\.Xauthority$" \ | sed 's/\/home\/\(.*\)\/.*/\1/'` if [ "$user" = "root" ]; then user="" fi fi # based on /home and ps if [ "$user" = "" ]; then IFS=" " ucnt=0 keepu="" for d in /home/* ; do u=`basename $d` if [ "$u" != "" ] && [ "$u" != "/home/*" ]; then test=`ps h -u $u -o "%U %c" 2> /dev/null` if [ "$test" != "" ]; then keepu="$u" (( ucnt += 1 )) fi fi done if (( ucnt == 1 )) && [ "$keepu" != "root" ]; then user="$keepu" fi fi # based on pwd if [ "$user" = "" ]; then if [ "${PWD:0:6}" = "/home/" ]; then u=`echo "$PWD" | sed 's/^\/home\/\([a-z0-9]*\).*/\1/'` if [ "$u" != "" ] && [ "$u" != "root" ] && [ -e "/home/$u" ] ; then user="$u" fi fi fi else user="$runuser" fi fi if [ "$user" = "root" ]; then log "sandfox: Warning: Running root in the sandbox is not recommended!" "quiet" elif [ "$user" = "" ]; then log "sandfox: Error: Could not determine sandbox user" "quiet"

  • log " Please specify --user USERNAME" "quiet" exit 2 fi # close if (( optcloseall + closecnt != 0 )); then if [ "$runuser" != "root" ]; then log "sandfox: Error: Closing a sandbox requires root" "quiet" exit 2 fi if (( optcloseall == 1 )); then if [ "$eventsfolder" != "" ]; then log ">>> rm -rf $eventsfolder/*" "verb" rm -rf $eventsfolder/* # this also stops daemons sync mkdir -p "$eventsfolder/tmp" chmod ugo+rwx,+t "$eventsfolder/tmp" 2> /dev/null fi rmbox "$mnt" else closex=0 while (( closex < closecnt )); do c="${closename[$closex]}" # sandbox exists? testdaemons=`ps -eo user,cmd | grep -v "grep" | grep "sandfox .*--daemon.*$eventsfolder/$c[[:blank:]]*$"` testmounts=`mount | grep " on $mnt/$c " | wc -l` if [ -e "$mnt/$c" ] || [ "$testdaemons" != "" ] || (( testmounts > 0 )); then if [ "$eventsfolder" != "" ]; then rm -rf "$eventsfolder/$c" fi rmbox "$mnt/$c" else log "sandfox: Warning: No such sandbox \"$c\"" "quiet" fi (( closex += 1 )) done fi fi # assume make if (( bindscnt + bindroscnt + copyscnt + hidescnt != 0 )) || (( profcnt > 1 )); then optmake=1 elif [ "$sandbox" != "" ] && [ "$bcmd" = "" ]; then optmake=1 fi # count usable daemons and assume make if (( optmake == 0 )) && [ "$bcmd" != "" ]; then if [ "$sandbox" = "" ]; then daemoncnt=`ps -u $user -o "%U %a" | grep -v "grep" | grep -c " .*sandfox .*--daemon"` else daemoncnt=`ps -u $user -o "%U %a" | grep -v "grep" | grep -c "sandfox .*--daemon.*/$sandbox[[:blank:]]*$"` fi if (( daemoncnt == 0 )); then

  • log "There are no usable sandbox daemons running for $user - make has been enabled" optmake=1 fi fi # need root? if [ "$runuser" != "root" ] && (( optmake + optcloseall + closecnt + optshell != 0 )); then log "sandfox: Error: action requires root; run with sudo or --help for info" "quiet" exit 2 fi # SECTION BELOW IS ROOT-ONLY if (( optmake == 1 )) && [ "$runuser" = "root" ]; then # create default profiles mkprofiles # load profiles profidx=0 loadedprofcnt=0 if [ "$bprog" != "" ] && [ -e "$profolder/$bprog.profile" ]; then prof[$profcnt]="$bprog" (( profcnt += 1 )) fi while (( profidx < profcnt )); do # Note: prof[] may grow as profiles are read loadprofile "${prof[$profidx]}" (( profidx += 1 )) done # sand newsand=0 if [ "$sandbox" != "" ]; then # sandbox exists? filecount=`find "$mnt/$sandbox" -mindepth 1 2> /dev/null | wc -l` testdaemons=`ps -eo user,cmd | grep -v "grep" | grep "sandfox .*--daemon.*/$sandbox[[:blank:]]*$"` testmounts=`mount | grep " on $mnt/$sandbox" | wc -l` if (( filecount > 0 )) || [ "$testdaemons" != "" ] || (( testmounts > 0 )); then newsand=0 else newsand=1 fi sandname="$sandbox" else if [ "$bprog" = "" ]; then p="${prof[1]}" if [ "${p:0:1}" = "/" ]; then p=`basename "$p" ".profile"` fi if [ "$p" != "" ]; then sandname="$p" else sandname="default" fi else sandname="$bprog"

  • fi sandnametmp="$sandname" while [ -e "$mnt/$sandname" ]; do randhex4 sandname="$sandnametmp-$randhex" done newsand=1 fi if (( newsand == 1 )); then log "Creating new sandbox \"$sandname\"" else log log "Updating sandbox $sandname" fi sand="$mnt/$sandname" # default folders mkdir -p "$mnt" chown root:root "$mnt" chmod go+rx,go-w "$mnt" mkdir "$sand" chown root:root "$sand" chmod go+rx,go-w "$sand" if [ ! -d "$sand" ]; then log "sandfox: Error: Could not create sand folder $sand" "quiet" exit 3 fi # check for required binds bindtmp=0 bindbin=0 bindetc=0 bindlib=0 bindusrlib=0 bindusrbin=0 binddev=0 bidx=0 while (( bidx < bindscnt )); do case "${binds[$bidx]}" in /tmp ) bindtmp=1 ;; /dev ) binddev=1 ;; /bin ) bindbin=1 ;; /etc ) bindetc=1 ;; /lib ) bindlib=1 ;; /usr ) bindusrbin=1 bindusrlib=1 ;; /usr/bin ) bindusrbin=1

  • ;; /usr/lib ) bindusrlib=1 ;; esac (( bidx += 1 )) done bidx=0 while (( bidx < bindroscnt )); do case "${bindros[$bidx]}" in /tmp ) bindtmp=1 ;; /dev ) binddev=1 ;; /bin ) bindbin=1 ;; /etc ) bindetc=1 ;; /lib ) bindlib=1 ;; /usr ) bindusrbin=1 bindusrlib=1 ;; /usr/bin ) bindusrbin=1 ;; /usr/lib ) bindusrlib=1 ;; esac (( bidx += 1 )) done if (( bindtmp == 0 )); then if [ "${eventsfolder:0:4}" = "/tmp" ]; then binds[$bindscnt]="$eventsfolder" (( bindscnt += 1 )) fi log "sandfox: Warning: Not binding /tmp may cause some programs to fail or hang" fi if (( binddev == 0 )); then binds[$bindscnt]="/dev/null" (( bindscnt += 1 )) fi if (( bindusrbin == 0 )); then bindros[$bindroscnt]="/usr/bin/inotifywait" (( bindroscnt += 1 )) bindros[$bindroscnt]="/usr/bin/whoami" (( bindroscnt += 1 )) bindros[$bindroscnt]="/usr/bin/basename" (( bindroscnt += 1 )) fi if (( bindusrlib == 0 )); then

  • f1=`find /usr/lib -maxdepth 1 -xtype f -name "libinotifytools*.so*" 2> /dev/null` if [ "$f1" != "" ]; then IFS=$'\n' for f in $f1 ; do bindros[$bindroscnt]="$f" (( bindroscnt += 1 )) done IFS=" " fi fi if (( bindbin + bindlib + bindetc != 3 )); then log "sandfox: Warning: Not binding /bin /etc and /lib may not allow" log " the chroot or su commands to run" fi if [ ! -e "/usr/bin/inotifywait" ]; then log "sandfox: Error: /usr/bin/inotifywait not found" "quiet" log " Arch use: pacman -S inotify-tools" "quiet" log " Ubuntu use: apt-get install inotify-tools" "quiet" exit 3 fi # binds for b in bindro bind copy hide ; do # step through list of binds to be processed bidx=0 eval bcnt=$b\scnt while (( bidx < bcnt )); do eval curb=\"\${$b\s[$bidx]}\" # current bind item curb=${curb//\$user/$user} log "Processing $b $curb" "verb" if [ -e "$curb" ] || [ "$b" = "hide" ]; then # check for duplicates dupefound=0 (( dupeidx = bidx - 1 )) while (( dupeidx > -1 )); do eval dupeb=\"\${$b\s[$dupeidx]}\" # possible duplicate item dupeb=${dupeb//\$user/$user} if [ "$dupeb" = "$curb" ]; then dupefound=1 break fi (( dupeidx -= 1 )) done # process if (( dupefound == 0 )); then test=`mount | grep " $sand$curb "` if [ "$test" != "" ]; then log "$b $sand$curb: already mounted" "verb" else case "$b" in bindro | bind ) # create mount point and recursively copy permissions # bind mount file or folder sandmount $b "$curb" "$sand$curb" ;; copy | hide )

  • if [ -d "$curb" ] || [ ! -e "$curb" ]; then # folder copy/hide # mount on tmpfs sandmount tmpfs "$curb" "$sand$curb" if [ -e "$curb" ]; then chmod --reference="$curb" "$sand$curb" 2> /dev/null chown --reference="$curb" "$sand$curb" 2> /dev/null else # non-existent hide permissions chmod ugo+rwx "$sand$curb" 2> /dev/null chown $user:$user "$sand$curb" 2> /dev/null fi if [ "$b" = "copy" ]; then log ">>> cp -ax \"$curb/.\" \"$sand$curb/.\"" "verb" cp -ax "$curb/." "$sand$curb/." if [ "$?" != "0" ]; then log "sandfox: Warning: cp reported an error copying $curb" "quiet" fi fi else # file copy/hide if [ "$b" = "copy" ]; then # copy if [ ! -e "$sand$curb" ]; then mdir=`dirname "$curb"` mkmount "$mdir" log ">>> cp -a \"$curb\" \"$sand$curb\"" "verb" cp -a "$curb" "$sand$curb" if [ "$?" != "0" ]; then log "sandfox: Warning: cp reported an error copying $curb" "quiet" fi else log "Cannot create copy of $curb" "verb" log " because it already exists in sandbox" "verb" fi else # hide sandmount bind "/dev/null" "$sand$curb" fi fi ;; esac fi fi fi (( bidx += 1 )) done done

  • sync # daemon running for user? test=`ps -u $user -o "%U %a" | grep -v "grep" \ | grep " .*sandfox .*--daemon .*$eventsfolder/$sandname[[:blank:]]*$"` if [ "$test" = "" ]; then # start daemon if [ "$logfile" != "" ]; then dlog="--logfile $logfile" else dlog="" fi if (( optverbose == 1 )); then verb="--verbose" else verb="" fi mkdir -p "$eventsfolder" chown root:root "$eventsfolder" 2> /dev/null chmod ugo+rwx,+t "$eventsfolder" 2> /dev/null if [ ! -d "$eventsfolder" ]; then log "sandfox: Error: Could not create events folder $eventsfolder" "quiet" exit 3 fi mkdir -p "$eventsfolder/tmp" chmod ugo+rwx,+t "$eventsfolder/tmp" 2> /dev/null cp "$0" "$eventsfolder/tmp/sandfox" chmod ugo+rx,go-w "$eventsfolder/tmp/sandfox" mkdir -p "$eventsfolder/$sandname" chmod ugo+rwx,+t "$eventsfolder/$sandname" log "Starting daemon as $user for sandbox \"$sandname\"..." "verb" log ">>> $wchroot $sand /bin/su $user -c \"$eventsfolder/tmp/sandfox --daemon $dlog $verb --watch $eventsfolder/$sandname\"" "verb" if (( optverbose == 1 )); then $wchroot $sand /bin/su $user -c "$eventsfolder/tmp/sandfox --daemon $dlog $verb --watch $eventsfolder/$sandname" & else $wchroot $sand /bin/su $user -c "$eventsfolder/tmp/sandfox --daemon $dlog $verb --watch $eventsfolder/$sandname" 2> /dev/null > /dev/null & fi sleep .5 test=`ps -u $user -o "%U %a" | grep -v "grep" \ | grep " .*sandfox .*--daemon .*$eventsfolder/$sandname[[:blank:]]*$"` if [ "$test" = "" ]; then log "sandfox: Warning: Could not start daemon - you may not be able" "quiet" log " to run additional programs in this sandbox" "quiet" fi fi fi # run command in sandbox if [ "$bcmd" != "" ]; then

  • if [ "$sandname" = "" ]; then # check/set sandbox name if [ "$sandbox" != "" ]; then sandname="$sandbox" else # find a sandbox daemon to run bcmd IFS=" " dtotal=0 dprefer="" dgood="" for d in $eventsfolder/* ; do if [ "$d" != "$eventsfolder/*" ] && [ "$d" != "" ] && [ -d "$d" ] \ && [ "$d" != "$eventsfolder/tmp" ] ; then dname=`basename "$d"` test=`ps -u $user -o "%U %a" | grep -v "grep" \ | grep " .*sandfox .*--daemon .*$d[[:blank:]]*$"` if [ "$test" != "" ]; then examples="$examples sandfox --sandbox $dname $bcmd\n" dgood="$dname" if [ "$dname" = "$bprog" ]; then dprefer="$dname" fi (( dtotal += 1 )) fi fi done if (( dtotal == 0 )); then log "sandfox: Error: There is no open sandbox to run $bprog" "quiet" exit 5 elif (( dtotal > 1 )); then log "sandfox: Warning: There is more than one sandbox open" log " To specify a sandbox:" echo -e "$examples" if [ "$dprefer" != "" ]; then sandname="$dprefer" else sandname="$dgood" fi else sandname="$dgood" fi fi fi # Check if firefox already running if [ "${bcmd%% *}" = "firefox" ]; then testrunning=`ps -u $user -o "%U %a" | grep -v "grep" | grep -v "sandfox" \ | grep -e " *${bcmd%% *}$" -e " *${bcmd%% *} "` if [ "$testrunning" != "" ]; then log "sandfox: Warning: An instance of ${bcmd%% *} is already running" fi fi

  • if [ "$runuser" = "root" ]; then # start directly if (( optshell == 1 )) || [ "$bprog" = "bash" ]; then log if [ "$bprog" = "bash" ]; then p="" else p=" running $bprog" fi log ">>> shell - you are $user$p in sandbox \"$sandname\" $wchroot $mnt/$sandname /bin/su $user -c \"$bcmd\"" "verb" if [ "$SUDO_USER" != "" ]; then ruser="$SUDO_USER" else ruser="ROOT" fi $wchroot $mnt/$sandname /bin/su $user -c "$bcmd" log log ">" else log "Starting $bprog as $user in sandbox \"$sandname\"..." log ">>> $wchroot $mnt/$sandname /bin/su $user -c \"$bcmd\" &" "verb" if (( verbose == 1 )); then $wchroot $mnt/$sandname /bin/su $user -c "$bcmd" & else $wchroot $mnt/$sandname /bin/su $user -c "$bcmd" 2> /dev/null > /dev/null & fi fi else log "Starting $bprog as $user in sandbox \"$sandname\"..." # start via daemon # get env of caller e=`env | grep -v "'" | sed "s/\([A-Z_]*=\)\(.*\)/\1\\\'\2\\\'/"` if [ "$e" != "" ]; then e="env -i ${e//$'\n'/ }" else e="" fi # build start script randhex4 cscript="$bprog-$randhex.sh" while [ -e "$eventsfolder/tmp/$cscript" ]; do randhex4 cscript="$bprog-$randhex.sh" done cat "$eventsfolder/tmp/$cscript" #!/bin/bash # sandfox automatic start script # It is safe to delete this file $e $bcmd & EOF chmod u+x,go-rwx "$eventsfolder/tmp/$cscript" # move start script to events folder mv -f "$eventsfolder/tmp/$cscript" "$eventsfolder/$sandname" log "Wrote start script $cscript ($bcmd)" "verb"

  • fi fi if (( optstatus == 1 )); then boxstatus fi exit # CHANGELOG: # 1.1.4: chroot discovery # added Firefox and Skype bindro=/home/\$user/.asoundrc # 1.1.3: added bindro /run/resolvconf to default Firefox profile # 1.1.2: accomodate change to remount bind usage # accomodate change to mtab bind mounts showing type # added /dev/nvidia0 & /dev/nvidiactl binds to default profiles # added bindro=/opt/firefox to default firefox profile # improved detection for 'firefox already running' warning # 1.1.1: accomodate recent change to ps line endings # 1.1.0: kills dbus-launch inside sandboxes before closing (lsof required) # 1.0.10: use tmpfs instead of none for mount source (due to new util-linux) # skype profile adds /opt/skype and disable note for Gentoo users # 1.0.9: permissions on mnt folders # removed uuidgen dependency # determine sandbox user with Xauthority # added default google-earth profile # 1.0.8: modification of daemon detection for non-standard ps # non-existent --sandbox triggers make # corrected --status mount count # 1.0.7: added /dev/video0 to skype profile (replaces /dev/video) # added disabled Lockdown X Access section to default profile # 1.0.6: added firefox bindro for ~/.Xauthority # added warning if firefox already running # 1.0.5: modification of daemon detection for non-standard ps # 1.0.4: corrected detection of running daemon with --verbose and --logfile # 1.0.3: corrected problems with sandboxes with similar names # 1.0.2: hide non-existent folder corrected # 1.0.0: handle /dev/urandom like /dev/random to prevent hangs # 0.9.6: Changed tmpfslimit to 100M # now allows successful bind=/dev/random for Firefox printing # added user-contributed skype profile (experimental)