Skip to content

Commit

Permalink
Remove environment variable $container
Browse files Browse the repository at this point in the history
Instead of inspecting the environment variable $container, check whether we are
able to do some operations and act responsively.
  • Loading branch information
arbuztw committed Sep 7, 2015
1 parent 8f43af6 commit ea642b8
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 69 deletions.
86 changes: 49 additions & 37 deletions host-bin/enter-chroot
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ chrootcmd() {
# env may be overridden when running in the background; don't let it fork.
local ret=0 oldtrap="$TRAP"
TRAP=''
env -i container="$container" chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$?
env -i chroot "$CHROOT" su -s '/bin/sh' -c "$*" - root || ret=$?
local pid="$!"
# $pid might not be set if env has not been redefined yet
if [ -n "$BACKGROUND" ] && [ -n "$pid" ]; then
Expand Down Expand Up @@ -323,7 +323,32 @@ bindmount() {
fi
mkdir -p "$target"
mount --bind $bindopts "$1" "$target"
if [ -n "$3" ]; then
# Determine whether we really need to remount or not by checking the existing
# mount options. We are doing this since remount is not allowed in containers.
if [ -n "$3" ] && ! checkmountopt "$target" "$3"; then
mount -i -o "remount,$3" "$target"
fi
}

# Recursively bind-mounts $1 into $CHROOT/${2:-"$1"} if $2 is not already mounted
# If $3 is specified, remounts with the specified options.
# If $1 starts with a -, it's considered options to the bind mount, and the rest
# of the parameters are shifted.
rbindmount() {
bindopts=''
if [ ! "${1#"-"}" = "$1" ]; then
bindopts="$1"
shift
fi
local target="`fixabslinks "${2:-"$1"}"`"
if mountpoint -q "$target"; then
return 0
fi
mkdir -p "$target"
mount --rbind $bindopts "$1" "$target"
# Determine whether we really need to remount or not by checking the existing
# mount options. We are doing this since remount is not allowed in containers.
if [ -n "$3" ] && ! checkmountopt "$target" "$3"; then
mount -i -o "remount,$3" "$target"
fi
}
Expand Down Expand Up @@ -357,35 +382,18 @@ else
firstrun='y'
fi

if [ -n "$container" ]; then
devmknod null
devmknod full
devmknod zero
devmknod tty
devmknod random
devmknod urandom
if [ ! -d "$CHROOT/dev/pts" ]; then
mkdir -p "$CHROOT/dev/pts"
fi
mount -t devpts devpts -o newinstance,ptmxmode=0666,mode=0620,gid=5 "$CHROOT/dev/pts"
ln -sf pts/ptmx "$CHROOT/dev/ptmx"
else
bindmount /dev
fi
bindmount /dev/pts
bindmount /dev/shm
if [ -n "$container" ]; then
bindmount /tmp /tmp
else
bindmount /tmp /tmp exec
fi
rbindmount /dev
bindmount /tmp /tmp exec
bindmount /proc
tmpfsmount /var/run 'noexec,nosuid,mode=0755,size=10%'
tmpfsmount /var/run/lock 'noexec,nosuid,nodev,size=5120k'
bindmount /var/run/dbus /var/host/dbus
bindmount /var/run/shill /var/host/shill
bindmount /var/lib/timezone /var/host/timezone
bindmount /var/run/crouton-ext
# If findnacld socket exists, bind-mount it into chroot.
if [ -S "/var/run/crouton-ext/socket" ]; then
bindmount /var/run/crouton-ext
fi
for m in /lib/modules/*; do
if [ -d "$m" ]; then
bindmount '-o ro' "$m"
Expand Down Expand Up @@ -662,20 +670,25 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then
# Launch systemd-logind if available and not already running
# Whitelisted for saucy and trusty
systemd_dir="`fixabslinks '/run/systemd'`"
if [ -z "$container" ] && [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \
if [ -x "$CHROOT/lib/systemd/systemd-logind" ] && \
[ ! -d "$systemd_dir" ] && \
[ "$CHROOTRELEASE" = 'saucy' -o "$CHROOTRELEASE" = 'trusty' ]; then
# Every piece of systemd code ever assumes that this directory exists
mkdir -p "$systemd_dir"

# Create systemd cgroup if necessary
start_systemd=true
if ! mountpoint -q "$CHROOT/sys/fs/cgroup/systemd"; then
mkdir -p "$CHROOT/sys/fs/cgroup/systemd"
mount -t cgroup -o nosuid,noexec,nodev,none,name=systemd systemd \
"$CHROOT/sys/fs/cgroup/systemd"
if ! mkdir -p "$CHROOT/sys/fs/cgroup/systemd" || \
! mount -t cgroup -o nosuid,noexec,nodev,none,name=systemd systemd \
"$CHROOT/sys/fs/cgroup/systemd"; then
start_systemd=false
fi
fi
# We cannot create/mount cgroup dirs in containers, so don't start systemd.
if $start_systemd; then
chrootcmd "/lib/systemd/systemd-logind >/dev/null 2>&1 </dev/null &"
fi
# systemd-logind doesn't fork
chrootcmd "/lib/systemd/systemd-logind >/dev/null 2>&1 </dev/null &"
fi

# Launch a daemon that can kill frecon when an X server is launched.
Expand All @@ -699,16 +712,15 @@ if [ ! "$NOLOGIN" = 1 ] && grep -q '^root:' "$passwd" 2>/dev/null; then
addtrap "(echo $$ >> '$CROUTONLOCKDIR/frecon') & :"
fi

# findnacld should have been started outside the container, so we don't need
# to start it again.
if [ -z "$container" ]; then
# If the socket file does not exist, it means findnacld is not started.
if [ ! -S "/var/run/crouton-ext/socket" ]; then
chrootcmd "/usr/local/bin/croutonfindnacld >/dev/null 2>&1 </dev/null &"
fi
fi

# Start the chroot and any specified command
if [ -n "$NOLOGIN" ]; then
env -i container="$container" TERM="$TERM" chroot "$CHROOT" "$@" || ret=$?
env -i TERM="$TERM" chroot "$CHROOT" "$@" || ret=$?
# Handle the return value when running the setup script.
if [ "$NOLOGIN" = 2 ]; then
# If it succeeded yet still exists, run it again.
Expand Down Expand Up @@ -738,7 +750,7 @@ else
fi

if [ $# = 0 -o -n "$LOGIN" ]; then
env -i container="$container" TERM="$TERM" chroot "$CHROOT" "$@" su - "$USERNAME" || ret=$?
env -i TERM="$TERM" chroot "$CHROOT" "$@" su - "$USERNAME" || ret=$?
else
# Escape out the command
cmd="export SHELL='$CHROOTSHELL';"
Expand All @@ -748,7 +760,7 @@ else
for param in "$@"; do
cmd="$cmd'`echo -n "$param" | sed "s/'/'\\\\\\''/g"`' "
done
env -i container="$container" TERM="$TERM" chroot "$CHROOT" \
env -i TERM="$TERM" chroot "$CHROOT" \
su -s '/bin/sh' -c "$cmd" - "$USERNAME" \
|| ret=$?
fi
Expand Down
6 changes: 4 additions & 2 deletions host-bin/mount-chroot
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ for NAME in "$@"; do
if ! mountpoint -q "$CHROOT"; then
if [ -z "$ENCRYPT" ]; then
mount --bind "$CHROOTSRC" "$CHROOT"
# Cannot remount in container
if [ -z "$container" ]; then
# Determine whether we really need to remount by checking the
# existing mount options. Doing this because we are not able to do
# remount in containers.
if ! checkmountopt "$CHROOT" "$MOUNTOPTS"; then
mount -i -o "remount,$MOUNTOPTS" "$CHROOT"
fi
continue
Expand Down
18 changes: 11 additions & 7 deletions host-bin/unmount-chroot
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,7 @@ unmount() {
# point actually ends with ' (deleted)')
# umount has a bug and may return 0 when many mount points cannot be
# unmounted, so we call it once per mount point ('-n 1')
if [ -n "$container" ]; then
arg='-l'
else
arg=''
fi
arg=''
while ! sed "s=\\\\040=//=g" /proc/mounts | cut -d' ' -f2 | filter \
| sed -e 's=//= =g;s/^\(\(.*\) (deleted)\)$/\1\n\2/' \
| sort -r | xargs --no-run-if-empty -d '
Expand Down Expand Up @@ -272,6 +268,11 @@ unmount() {
if [ -z "$printonly" ]; then
echo "Sending SIG$SIGNAL to processes under $CHROOTSRC..." 1>&2
fi
# If there is no process running under $CHROOTSRC and we cannot
# unmount, then use lazy unmount.
# FIXME: This is a hack for running in containers, since we cannot
# unmount recursive bindmount in it.
arg='-l'
for root in /proc/*/root; do
if [ ! -r "$root" ] \
|| [ ! "`readlink -f "$root"`" = "$base" ]; then
Expand All @@ -285,6 +286,7 @@ unmount() {
if [ -z "$printonly" ]; then
kill "-$SIGNAL" "$pid" 2>/dev/null || true
fi
arg=''
done

# Escalate
Expand Down Expand Up @@ -326,10 +328,12 @@ done

# Re-disable USB persistence (the Chromium OS default) if we no longer
# have chroots running with a root in removable media
if [ -z "$container" ] && checkusage "$ROOT/media"; then
if checkusage "$ROOT/media"; then
for usbp in /sys/bus/usb/devices/*/power/persist; do
if [ -e "$usbp" ]; then
echo 0 > "$usbp"
# Don't fail since we don't have permission to write /sys/* if we are in
# container.
echo 0 > "$usbp" || true
fi
done
fi
Expand Down
37 changes: 34 additions & 3 deletions installer/functions
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,37 @@ undotrap() {
settrap "$TRAP"
}

# Check if we are able to mknod.
capmknod() {
local tmp=`mktemp -d --tmpdir=/tmp 'crouton-mknod.XXX'`
if ! mknod "$tmp/test-mknod" c 0 0; then
return 1
fi
rm -rf "$tmp"
return 0
}

# Check whether $1 is mounted with options $2.
# We check the options of a mount point by inspecting /proc/mounts.
# For options dev, suid and exec, since they will not show up in /proc/mounts,
# we check whether their opposite options (nodev, nosuid, noexec) exists.
checkmountopt() {
for opt in ${2//,/ }; do
case $opt in
dev|suid|exec)
if ! awk -v dir="$1" -v opt="no$opt(,|$)" \
'$2 == dir && $4 ~ opt { exit 1 }' "/proc/mounts"; then
return 1
fi;;
*)
if ! awk -v dir="$1" -v opt="$opt(,|$)" \
'$2 == dir && $4 !~ opt { exit 1 }' "/proc/mounts"; then
return 1
fi;;
esac
done
}

# Works mostly like built-in getopts but silently coalesces positional arguments.
# Does not take parameters. Set getopts_string prior to calling.
# Sets getopts_var and getopts_arg.
Expand Down Expand Up @@ -156,9 +187,9 @@ release() {
# sure the kernel does not panic (this is the default configuration of a vanilla
# kernel). See crbug.com/260955 for details.
disablehungtask() {
if [ -z "$container" ]; then
echo 0 > /proc/sys/kernel/hung_task_panic
fi
# Don't fail since we do not have permission to write /proc/sys/* if we are
# in container.
echo 0 > /proc/sys/kernel/hung_task_panic || true
}

# Run an awk program, without buffering its output.
Expand Down
8 changes: 4 additions & 4 deletions installer/ubuntu/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Check your internet connection or proxy settings and try again.'
fi
fi

# Patch debootstrap so that it retries downloading packages
# Patch debootstrap so that it retries downloading packages and not mounting /sys
echo 'Patching debootstrap...' 1>&2
if awk '
t == 3 && /warning RETRY/ { print "sleep 1"; t=4 }
Expand All @@ -42,7 +42,7 @@ if awk '
sub(/continue 2; fi/, "failed=y")
t=1
}
/if \[ -d \"\$TARGET\/sys\" \] && \\/ { sub(/if/, "if [ -z \"$container\" ] \&\&") }
/if \[ -d \"\$TARGET\/sys\" \] && \\/ { sub(/if/, "if false \&\&") }
1
END { if (t != 4) exit 1 }
' "$tmp/functions" > "$tmp/functions.new"; then
Expand All @@ -67,8 +67,8 @@ if [ ! -f "$tmp/scripts/$RELEASE" ]; then
ln -s "$tmp/scripts/$BOOTSTRAP_RELEASE" "$tmp/scripts/$RELEASE"
fi

# We are not able to mknod in containers, so make a fake mknod for debootstrap.
if [ -n "$container" ]; then
# Create a fake mknod for debootstrap if we don't have CAP_MKNOD.
if ! capmknod; then
mkdir "$tmp/bin"
echo "touch \$1" > "$tmp/bin/mknod"
chmod +x "$tmp/bin/mknod"
Expand Down
24 changes: 8 additions & 16 deletions installer/ubuntu/prepare
Original file line number Diff line number Diff line change
Expand Up @@ -219,38 +219,30 @@ export DEBIAN_FRONTEND=noninteractive

# Run debootstrap second stage if it hasn't already happened
if [ -r /debootstrap ]; then
# Debootstrap doesn't like anything mounted under /sys or /var when it runs
# Debootstrap doesn't like anything mounted under /var when it runs.
# We request a re-mount after bootstrapping, so these mounts will be fixed.
# We also can't detect the mounts properly due to the chroot, so we have to
# recursively find mountpoints under /sys, and hardcode /var umounts.
# However, if we are in container, debootstrap cannot mount /sys, so don't
# unmount it.
if [ -z "$container" ]; then
find /sys/* -maxdepth 2 -depth -type d \
-exec mountpoint -q {} \; -exec umount {} \;
else
# hardcode /var umounts.
if mountpoint -q '/var/run/crouton-ext'; then
umount '/var/run/crouton-ext'
fi
umount '/var/run/lock' '/var/run'
# Create a fake mknod if we are in container.
if [ -n "$container" ]; then
# Create a fake mknod for debootstrap if we don't have CAP_MKNOD.
if ! capmknod; then
cp /bin/mknod /bin/mknod.old
echo "touch \$1" > /bin/mknod
fi
# Start the bootstrap
/debootstrap/debootstrap --second-stage
if [ -n "$container" ]; then
# Mark makedev as installed.
# If we cannot mknod, the installation of makedev will fail, so mark it as
# installed manually.
if ! capmknod; then
awk '
BEGIN { matched = 0 }
/^Package: makedev$/ { matched = 1 }
matched == 1 && /^Status:/ { sub($4, "installed"); matched = 0 }
1' /var/lib/dpkg/status > /var/lib/dpkg/status.new
mv -f /var/lib/dpkg/status.new /var/lib/dpkg/status

# Deny all services to start in container.
echo exit 101 > /usr/sbin/policy-rc.d
chmod +x /usr/sbin/policy-rc.d
fi
# Clean contents of /var/run (since we'll always be mounting over it).
rm -rf --one-file-system /var/run/*
Expand Down

0 comments on commit ea642b8

Please sign in to comment.