#! /bin/sh # $NetBSD: mksandbox,v 1.19 2023/12/05 20:45:27 agc Exp $ # Copyright (c) 2002,2012 Alistair Crooks # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Usage: mksandbox [--mounthost=host] [--pkgsrc=dir] # [--rodirs=dir1,...] [--rwdirs=dir1,...] # [--src=srcdir] [--xsrc=xsrcdir] # [--without-src] [--without-pkgsrc] [--without-xsrc] # [--without-x] [--verbose] sandbox-dir # # A small shell script to set up a sandbox (usually for a pkgsrc bulk # build), using null mounts. pkgsrc=/usr/pkgsrc src=/usr/src xsrc=/usr/xsrc rodirs= rwdirs= with_pkgsrc=yes with_x=yes kernel="" sandboxWriteDirs="" sandboxMountDirs="/bin /sbin /lib /libexec /usr/X11R7 /usr/bin /usr/games /usr/include /usr/lib /usr/libdata /usr/libexec /usr/lkm /usr/share /usr/sbin /var/mail" sandboxEmptyDirs="/var/run /var/log /var/spool/lock /var/spool/mqueue" sandboxEmptyFiles="/var/run/utmp /var/run/utmpx /var/log/wtmp /var/log/wtmpx /var/log/lastlog /var/log/lastlogx" usage() { echo "usage: mksandbox [--mounthost=host] [--rodirs=dir1,...] [--rwdirs=dir1,...]" echo " [--pkgsrc=dir] [--src=srcdir] [--xsrc=xsrcdir]" echo " [--without-src] [--without-pkgsrc] [--without-xsrc]" echo " [--without-x] [--verbose] sandbox-dir" exit 1 } err() { echo "error: $1" exit 1 } # by default, don't require src and xsrc to be available need_src=no need_xsrc=no opsys=`uname -s` case "$opsys" in Darwin) bmakeprog=bmake chmodprog=/bin/chmod chownprog=/usr/sbin/chown cpprog=/bin/cp gtarprog=/usr/bin/gnutar idprog=/usr/bin/id kernel=/mach_kernel mkdirprog="/bin/mkdir -p" mountflags="-t nfs" mounthost="localhost" mountprog=/sbin/mount paxprog=/bin/pax sedprog=/usr/bin/sed sandboxEmptyDirs="$sandboxEmptyDirs /var/root" sandboxMountDirs="$sandboxMountDirs /usr/llvm-gcc-4.2 /usr/X11 /System/Library /Library" sandboxWriteDirs="$sandboxWriteDirs /Library/Server/Mail/Data" ;; DragonFly) bmakeprog=bmake chmodprog=/bin/chmod chownprog=/usr/sbin/chown cpprog=/bin/cp gtarprog=/usr/bin/tar idprog=/usr/bin/id mkdirprog="/bin/mkdir -p" mountflags="-t null" mountprog=/sbin/mount paxprog=/bin/pax sedprog=/usr/bin/sed sandboxEmptyDirs="$sandboxEmptyDirs /var/spool/dma" ;; FreeBSD) bmakeprog=bmake chmodprog=/bin/chmod chownprog=/usr/sbin/chown cpprog=/bin/cp gtarprog=/usr/bin/tar idprog=/usr/bin/id mkdirprog="/bin/mkdir -p" mountflags="-t nullfs" mountprog=/sbin/mount paxprog=/bin/pax sedprog=/usr/bin/sed ;; Interix) echo >&2 "This script cannot be used on Interix; a different procedure is required." echo >&2 "(To be documented.)" exit 1 ;; Linux) bmakeprog=bmake chmodprog=/bin/chmod chownprog=/bin/chown cpprog=/bin/cp gtarprog=/bin/tar idprog=/usr/bin/id mkdirprog="/bin/mkdir -p" mountflags="--bind" if [ -f /bin/mount ]; then mountprog=/bin/mount else mountprog=/sbin/mount fi paxprog="" sedprog=/bin/sed sandboxMountDirs="$sandboxMountDirs /lib64 /usr/lib64 /usr/kerberos" sandboxWriteDirs="$sandboxWriteDirs /proc" ;; NetBSD) bmakeprog=make chmodprog=/bin/chmod chownprog=/usr/sbin/chown cpprog=/bin/cp gtarprog=/usr/bin/tar idprog=/usr/bin/id kernel=/netbsd mkdirprog="/bin/mkdir -p" mountflags="-t null" mountprog=/sbin/mount paxprog=/bin/pax sedprog=/usr/bin/sed need_src=yes need_xsrc=yes ;; SunOS) bmakeprog=bmake chmodprog=/usr/bin/chmod chownprog=/usr/bin/chown cpprog=/usr/bin/cp gtarprog="" idprog=/usr/xpg4/bin/id mkdirprog="/usr/bin/mkdir -p" mountflags="-F lofs" mountprog=/sbin/mount paxprog=/bin/pax sedprog=/usr/xpg4/bin/sed sandboxMountDirs="/bin /sbin /kernel /lib /proc /opt/SUNWspro /usr/X11R6 /usr/5bin /usr/bin /usr/ccs /usr/dt /usr/games /usr/include /usr/lib /usr/openwin /usr/share /usr/sbin /usr/sadm /usr/sfw /usr/ucb /usr/ucblib /usr/xpg4 /var/mail /var/sadm" sandboxEmptyDirs="$sandboxEmptyDirs /usr/tmp /var/tmp" ;; *) echo "Unknown Operating System ($opsys) - good luck" bmakeprog=bmake chmodprog=chmod chownprog=chown cpprog=cp gtarprog="tar" idprog="id" mkdirprog="mkdir -p" mountflags="-t null" mountprog=mount paxprog=pax sedprog=sed ;; esac while [ $# -gt 0 ]; do case "$1" in --mounthost=*) mounthost=`echo $1 | $sedprog -e 's|^--mounthost=||'` ;; --pkgsrc=*) pkgsrc=`echo $1 | $sedprog -e 's|^--pkgsrc=||'` ;; --src=*) src=`echo $1 | $sedprog -e 's|^--src=||'` ;; --xsrc=*) xsrc=`echo $1 | $sedprog -e 's|^--xsrc=||'` ;; --rodirs=*) rodirs=`echo $1 | $sedprog -e 's|^--rodirs=||'` ;; --rwdirs=*) rwdirs=`echo $1 | $sedprog -e 's|^--rwdirs=||'` ;; --without-pkgsrc) with_pkgsrc=no ;; --without-src) need_src=no ;; --without-xsrc) need_xsrc=no ;; --without-x) with_x=no ;; --verbose) set -x ;; -*) usage ;; *) break ;; esac shift done if [ $# -ne 1 ]; then usage fi if [ "$with_x" = "no" ]; then need_xsrc=no fi if [ `$idprog -u` -ne 0 ]; then err "You must be root to run this script." fi if [ -n "$mounthost" ]; then mounthost="$mounthost:" fi if [ ! -d $pkgsrc -a "$with_pkgsrc" = "yes" ]; then err "pkgsrc directory $pkgsrc does not exist." fi if [ ! -d $src -a "$need_src" = "yes" ]; then err "source directory $src does not exist." fi if [ ! -d $xsrc -a "$need_xsrc" = "yes" ]; then err "xsrc directory $xsrc does not exist." fi sandbox=$1 sandbox_script="$sandbox/sandbox" if [ "$with_pkgsrc" = "yes" ]; then packages=`(cd $pkgsrc/pkgtools/lintpkgsrc; $bmakeprog show-var VARNAME=PACKAGES)` distfiles=`(cd $pkgsrc/pkgtools/lintpkgsrc; $bmakeprog show-var VARNAME=DISTDIR)` localbase=`(cd $pkgsrc/pkgtools/lintpkgsrc; $bmakeprog show-var VARNAME=LOCALBASE)` pkg_dbdir=`(cd $pkgsrc/pkgtools/lintpkgsrc; $bmakeprog show-var VARNAME=PKG_DBDIR)` localpatches=`(cd $pkgsrc/pkgtools/lintpkgsrc; $bmakeprog show-var VARNAME=LOCALPATCHES)` test -d "$localpatches" || echo "WARNING: LOCALPATCHES directory does not exist - ignoring" fi $mkdirprog $sandbox sandbox="`(cd $sandbox && pwd)`" cat > $sandbox_script <> $sandbox_script done for d in $sandboxWriteDirs; do test -d $d || continue; $mkdirprog $sandbox$d; $mountprog $mountflags $mounthost$d $sandbox$d; echo "$mounthost$d $d rw \\" >> $sandbox_script done echo "Making /tmp in $sandbox" $mkdirprog $sandbox/tmp $sandbox/var/tmp $chmodprog 1777 $sandbox/tmp $sandbox/var/tmp $idprog games >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "Making /var/games in $sandbox" $mkdirprog $sandbox/var/games $chownprog games:games $sandbox/var/games $chmodprog 2775 $sandbox/var/games fi for d in $sandboxEmptyDirs; do test -d $d || continue echo "Making $d in $sandbox" $mkdirprog $sandbox$d done for f in $sandboxEmptyFiles; do test -f $f || continue echo "Making $f in $sandbox" $cpprog /dev/null $sandbox$f done if [ "$need_src" = "yes" ]; then echo "Mount $src from $sandbox" $mkdirprog $sandbox/usr/src $mountprog $mountflags -r $mounthost$src $sandbox/usr/src echo "$mounthost$src /usr/src ro \\" >> $sandbox_script fi if [ "$with_pkgsrc" = "yes" ]; then echo "Mount $pkgsrc from $sandbox" $mkdirprog $sandbox/usr/pkgsrc $mountprog $mountflags $mounthost$pkgsrc $sandbox/usr/pkgsrc echo "$mounthost$pkgsrc /usr/pkgsrc rw \\" >> $sandbox_script echo "Mounting $packages and $distfiles from $sandbox" $mkdirprog $sandbox/$packages $sandbox/$distfiles $mkdirprog $packages $distfiles $mountprog $mountflags $mounthost$packages $sandbox/$packages $mountprog $mountflags $mounthost$distfiles $sandbox/$distfiles echo "$mounthost$packages $packages rw \\" >> $sandbox_script echo "$mounthost$distfiles $distfiles rw \\" >> $sandbox_script if [ -n "$localpatches" ] && [ -d "$localpatches" ]; then echo "Mounting $localpatches from $sandbox" $mkdirprog $sandbox/$localpatches $mountprog $mountflags $mounthost$localpatches $sandbox/$localpatches echo "$mounthost$localpatches $localpatches rw \\" >> $sandbox_script fi fi if [ "$need_xsrc" = "yes" ]; then echo "Mount $xsrc from $sandbox" $mkdirprog $sandbox/usr/xsrc $mountprog $mountflags -r $mounthost$xsrc $sandbox/usr/xsrc echo "$mounthost$xsrc /usr/xsrc ro \\" >> $sandbox_script fi if [ -n "$rodirs" ]; then for dir in `echo $rodirs | $sedprog -e 's/,/ /g'`; do echo "Mount $dir from $sandbox" $mkdirprog $sandbox$dir $mountprog $mountflags -r $mounthost$dir $sandbox$dir case "$opsys" in Linux) $mountprog $mountflags -o remount,bind,ro $mounthost$dir $sandbox$dir ;; esac echo "$mounthost$dir $dir ro \\" >> $sandbox_script done fi if [ -n "$rwdirs" ]; then for dir in `echo $rwdirs | $sedprog -e 's/,/ /g'`; do echo "Mount $dir from $sandbox" $mkdirprog $sandbox$dir $mountprog $mountflags $mounthost$dir $sandbox$dir echo "$mounthost$dir $dir rw \\" >> $sandbox_script done fi date > $sandbox/.sandbox_mounted cat >> $sandbox_script < \$sandbox/.sandbox_mounted ;; xumount) if [ ! -s \$sandbox/.sandbox_mounted ]; then echo \$sandbox not mounted && exit 1 fi set dummy \`r3 \$fses\` shift while [ \$# -ge 3 ]; do fs=\$1; shift mntpoint=\$1; shift dummy=\$1; shift umount \$sandbox/\$mntpoint done case \$opsys in Linux) umount \$sandbox/dev/shm umount \$sandbox/dev ;; Darwin|DragonFly|FreeBSD) umount \$sandbox/dev ;; SunOS) umount \$sandbox/dev/fd umount \$sandbox/dev ;; esac rm -f \$sandbox/.sandbox_mounted ;; xchroot) if [ ! -s \$sandbox/.sandbox_mounted ]; then echo \$sandbox not mounted && exit 1 fi case x\$2 in x) rootshell=/bin/ksh ;; *) rootshell="\$2" ;; esac script="\$sandbox/tmp/script.\$\$" echo "#!/bin/sh" > \$script echo "ENV=/etc/shrc \$rootshell" >> \$script chmod +x \$script ENV=/etc/shrc chroot \$sandbox /tmp/\`basename \$script\` rm -f \$script ;; xismounted) if [ -s \$sandbox/.sandbox_mounted ]; then echo \$sandbox is mounted && exit 0 else echo \$sandbox is not mounted && exit 1 fi ;; *) if [ \$# -eq 0 ]; then set dummy /bin/sh shift fi chroot \$sandbox "\$@" ;; esac EOS chmod +x $sandbox_script case $opsys in Darwin) $cpprog /var/run/resolv.conf $sandbox/var/run/resolv.conf ;; Linux) if [ -f /run/resolvconf/resolv.conf ]; then $mkdirprog $sandbox/run/resolvconf $cpprog /run/resolvconf/resolv.conf $sandbox/run/resolvconf/resolv.conf fi ;; SunOS) $cpprog /etc/mnttab $sandbox/etc/mnttab ;; *) esac echo "Sandbox creation is now complete" exit 0