Page 1 of 1

Bash script to create a chroot jail

Posted: Sun 29 Nov 2009, 13:54
by jamesjeffries2
I am trying to write a script that will create a basic chroot jail. Here is the code so far:

Code: Select all

#!/bin/bash

# debugging only
rm -rf /tmp/chroot

# Set up chroot directory
mkdir /tmp/chroot
pushd /tmp/chroot
mkdir bin etc lib var home

# Copy in the relevant parts of the system
APPS="/bin/bash /bin/ls /bin/mkdir /bin/mv /bin/pwd /bin/rm /bin/ping"
for prog in $APPS; do
echo "===========";
echo $prog;
#sleep 1
cp $prog ./ --parents

# obtain a list of related libraries
ldd $prog > /dev/null
if [ "$?" = 0 ] ; then
LIBS=`ldd $prog | awk '{ print $3 }' | grep -v \(`
echo $LIBS
for l in $LIBS; do
#mkdir -p ./`dirname $l` > /dev/null 2>&1
cp $l ./ --parents
done
fi
done

popd

# change root
chroot /tmp/chroot /bin/bash
however when i run it I get the following error:

Code: Select all

chroot: can't execute '/bin/bash': No such file or directory

Anyone got much experience with chroot that might help?

Cheers,
Jim

Posted: Sun 29 Nov 2009, 14:15
by big_bass
Hey jamesjeffries2

I use chroots a lot
on puppy , slackware and slitaz

now there are several way of doing this depending how complete you need it


.1.)simple for building basic packages
2.)runnnig the os for testing
3.) full os running same as a standard install

and there is always tweaking required to set it up
depending on the version

Joe

Posted: Sun 29 Nov 2009, 15:12
by jamesjeffries2
Option 2 looks best to me.

This script was more just to see if I could get it working at a very basic level.

I can get it to work if I copy the whole of /bin and /lib accross, but want to see if I can build it up from the nothing to see what I can learn from it.

But also could be useful for packaging too, never occurred to me to use it for that before

Posted: Wed 02 Dec 2009, 07:00
by amigo
This is a little long, but I#ll post the whole thing -which is just a part of a routine for installing software in a chroot jail:

Code: Select all

# This file is part of the src2pkg program:
# Copyright 2005-2010 Gilbert Ashley <amigo@ibilio.org>
# src2pkg is released under the GNU General Public License Version 2

# This method installs all files into a 'false root' directory, the PKG_DIR,
# but uses unionfs and chroot rather than sentry.  This usually works when
# using DESTDIR and JAIL is not supported by the Makefiles and is less
# intrusive than installing to the real root directory, backing up overwritten
# files and then restoring them

## free_union
free_union() {
umount -l "$UNION_DIR/OBJ_DIR" &> /dev/null
umount -l "$UNION_DIR"/tmp &> /dev/null
umount -l "$UNION_DIR"/var/tmp &> /dev/null
umount -l "$UNION_DIR"/sys &> /dev/null
umount -l "$UNION_DIR"/proc &> /dev/null
umount -l "$UNION_DIR"/dev &> /dev/null
umount -l "$UNION_DIR" &> /dev/null
}
## User cancelled at a 'sensitive' spot, so scold them!
trap_union_int() {
  echo
  echo $RED"   *** OUCH!!! *** "$NORMAL"Dangerous cancellation"
  echo "   Please don't cancel while fake_install is running."
  echo "   Cleaning up hanging mounts on unionfs."
  free_union
  FAILED="CANCELLED"
  case $AUDIO_NOTIFICATION in
	BEEP)	echo -ne '\a';sleep .5;echo -ne '\a' ;;
	SAY)
		case $TTS_ENGINE in
			flite) flite "Dangerous cancellation" 2> /dev/null ;;
			festival) echo "Dangerous cancellation" |festival --tts 2> /dev/null ;;
		esac
		;;
	PLAY)	play /usr/share/src2pkg/sounds/ouch &> /dev/null ;;
  esac
  exit
}

install_to_union_root() {
echo $BLUE"Installing in UNION chroot - "$NORMAL"Using: '$INSTALL_COMMAND $INSTALL_RULE'"$NORMAL
UNION_DIR_NAME=$NAME-$VERSION-union-$BUILD$SIG
UNION_DIR="$PKG_BUILDS_DIR"/$UNION_DIR_NAME
EXCL_DIR_NAME=$NAME-$VERSION-excl-$BUILD$SIG
EXCL_DIR="$PKG_BUILDS_DIR"/$EXCL_DIR_NAME

mkdir -p "$PKG_DIR"

# don't do full recursive delete - losing important files if one of the
# excludes doesn't properly umount is a Very Bad Thing.
rmdir "$UNION_DIR" 2> /dev/null
rm -rf "$EXCL_DIR"
mkdir -p "$UNION_DIR"
mkdir -p "$EXCL_DIR"

# create mount-points for dirs we will be binding
mkdir -p "$EXCL_DIR"/dev
mkdir -p "$EXCL_DIR"/proc
mkdir -p "$EXCL_DIR"/sys
mkdir -p "$EXCL_DIR"/var/tmp
mkdir -p "$EXCL_DIR"/tmp


case "$UNIONFS_TYPE" in
   "unionfs")
      mount -t unionfs -o dirs="$PKG_DIR"=rw:/=ro:"$EXCL_DIR"=ro unionfs "$UNION_DIR"
   ;;
   "unionfs-fuse")
      unionfs -o cow "$PKG_DIR"=RW:/=RO:"$EXCL_DIR"=RO "$UNION_DIR"
   ;;
esac

# set the trap_union_int to be sure we don't leave mounts hanging if interrupted
trap trap_union_int 2

# bind the system dirs in the union root
mount --bind /dev "$UNION_DIR"/dev
mount --bind /proc "$UNION_DIR"/proc
mount --bind /sys "$UNION_DIR"/sys
mount --bind /var/tmp "$UNION_DIR"/var/tmp
mount --bind /tmp "$UNION_DIR"/tmp

# create an explicit and uniquely-named OBJ_DIR under the UNION_DIR. We need to do this because if the
# original OBJ_DIR is on a separate filesystem it won't be there under the UNION_DIR unless it is explicitly
# bind-mounted. We create a unique directory so we can safely and easily remove it afterwards.
# We do this in the UNION_DIR because it is RW -sometimes install create new files so we need OBJ_DIR writable
#mkdir -p "$EXCL_DIR"/OBJ_DIR
mkdir -p "$UNION_DIR"/OBJ_DIR
# bind the $OBJ_DIR in the union root
mount --bind "$OBJ_DIR" "$UNION_DIR"/OBJ_DIR

# we could use fakeroot for this step, but we'll need to also use it later when checking and correcting ownerships and perms
if [[ $LOG_COMMANDS = "YES" ]] ; then
	#
	if ! [[ $LOG_DIR ]] ; then
		LOG_DIR="$OBJ_DIR"
	elif [[ "$LOG_DIR" != "$CWD" ]] && [[ "${LOG_DIR:0:1}" != "/" ]] ; then
		echo $YELLOW"Warning! "$NORMAL"LOG_DIR is set to an invalid path."
		echo "         It must be set to \$CWD or an absolute path."
	fi
	echo $BLUE"Logging output to: "$NORMAL"LOG_DIR/$NAME-make-install.log"
	( chroot "$UNION_DIR" /bin/sh -c "cd OBJ_DIR && ${INSTALL_COMMAND} ${INSTALL_RULE} &> $NAME-make-install.log ; exit" )
	if ! [[ -f "$LOG_DIR"/$NAME-make-install.log ]] ; then
		cp "$OBJ_DIR"/$NAME-make-install.log "$LOG_DIR"/
	fi
elif [[ $QUIET = "YES" ]] ; then
	( chroot "$UNION_DIR" /bin/sh -c "cd OBJ_DIR && ${INSTALL_COMMAND} ${INSTALL_RULE} &> /dev/null ; exit" )
else
	( chroot "$UNION_DIR" /bin/sh -c "cd OBJ_DIR && ${INSTALL_COMMAND} ${INSTALL_RULE} ; exit" )
fi
RETVAL=$?

# unmount the OBJ_DIR
umount -l "$UNION_DIR/OBJ_DIR"
# after unmounting the $UNION_DIR/OBJ_DIR, remove
# the dir so it doesn't get included in the package
# ( cd "$UNION_DIR" && rm -rf OBJ_DIR )
rmdir "$UNION_DIR"/OBJ_DIR || echo $YELLOW"Warning - "$NORMAL"Unable to remove OBJ_DIR!"
# unmount the system dirs from the union root
umount -l "$UNION_DIR"/tmp
umount -l "$UNION_DIR"/var/tmp
umount -l "$UNION_DIR"/sys
umount -l "$UNION_DIR"/proc
umount -l "$UNION_DIR"/dev

if umount "$UNION_DIR" ; then
	true
else 
	echo $YELLOW"Warning - "$NORMAL"Forcing umount of UNION_DIR!"
	umount -l "$UNION_DIR"
fi

rmdir "$UNION_DIR" || echo $YELLOW"Warning - "$NORMAL"Unable to remove UNION_DIR!"

( cd "$PKG_BUILDS_DIR" && rm -rf $EXCL_DIR_NAME )

# Delete all metadata - really shouldn't be thrown away like this
case "$UNIONFS_TYPE" in
	"unionfs")
	find "$PKG_DIR" -name ".wh.*" -exec rm "{}" ";"
	;;
	"unionfs-fuse")
	rm -rf "$PKG_DIR/.unionfs/"
	;;
esac

# some tentative error handling
if [ $RETVAL -gt 0 ] ; then
	# FIXME: what post-processing needs to happen?
	echo "Failed"
	FAILED="CHROOT install in $FUNCNAME"
fi

}
The main points to obeserve are: don't copy file over as it takes a very long time and uses lots of disk space. Instead use 'miunt bind...' to duplicate the content; you don't have to use unionfs mounts, depending on what you are trying to do.
Maybe you should tell us what you are trying to do as there may be a better way than going to the trouble of creating a chroot.

Posted: Wed 02 Dec 2009, 17:02
by jamesjeffries2
Just wanted to see how minimal I could get something to just run a web browser.

So that people could have completely secure browsing as the rest of the filesystem would be completely unreachable.

Not had much chance to look at this in the last couple of days due to work, but thinking about it im pretty sure /tmp doesnt allow you to execute stuff, so that could well be the problem.

EDIT: tried it not in /tmp but still no luck.

Cheers amigo thats quite useful, ill have a proper look at it later.

Posted: Wed 02 Dec 2009, 17:53
by big_bass
jamesjeffries2

Code: Select all

 completely secure browsing as the rest of the filesystem would be completely unreachable. 
No, that wont work
all you would have to do would exit to prompt and type

Code: Select all

exit 
not much for security there :shock:

to leave the chroot

and you would have the full control

there are better ways and thats add user
just for browsing ? secured base OS
why not slitaz its already set up that way



Joe

Posted: Thu 18 Feb 2010, 10:07
by aragon
although an old post, i thought i post a link i found today about a 'bash-sandbox'

http://igurublog.wordpress.com/download ... /#programs

aragon