/
chroot-startstop.sh.in
executable file
·136 lines (119 loc) · 4.01 KB
/
chroot-startstop.sh.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/bin/sh
# @configure_input@
# Script to setup chroot environment extras needed to perform a juding run.
#
# This script will (bind) mount a minimal set of subdirectories from a
# pre-built chroot tree into the actual chroot environment that is
# created for each judging (as well as the proc FS and a few device
# files). Afterwards it is also called to cleanup.
#
# You can adapt this script to your environment, e.g. if you need to make
# more/other subdirectories available in the chroot environment.
#
# See bin/dj_make_chroot.sh for a script to generate the
# chroot environment. Note that if you modify paths
# in this script, then the associated sudo rules (see
# etc/sudoers-domjudge) must also be updated.
#
# This script will be called from judgedaemon.main.php in the root
# directory of the chroot environment with one parameter, either:
# - 'check' to perform some basic validation checks;
# - 'start' to setup; or
# - 'stop' to destroy the chroot environment.
#
# We always use 'sudo -n <command> < /dev/null' to make sure that sudo
# doesn't try to ask for a password, but just fails.
# Exit on error:
set -e
# Chroot subdirs needed: (optional lib64 only needed for amd64 architecture)
SUBDIRMOUNTS="etc usr lib bin"
if [ "$(uname -m)" = "x86_64" ]; then
SUBDIRMOUNTS="$SUBDIRMOUNTS lib64"
fi
# Location of the pre-built chroot tree and where to bind mount from:
CHROOTORIGINAL="@judgehost_chrootdir@"
dj_umount() {
set +e
if ! sudo -n umount "$1" < /dev/null; then
>&2 echo "umount '$1' didn't succeed, trying harder"
if ! sudo -n umount -f -vvv "$1" < /dev/null; then
>&2 echo "umount '$1' failed twice"
>&2 lsof -w +c 15 +D "$1"
exit 1
fi
fi
set -e
}
case "$1" in
check)
if [ ! -d "$CHROOTORIGINAL" ]; then
>&2 echo "chroot dir '$CHROOTORIGINAL' does not exist, run dj_make_chroot"
exit 2
fi
for i in $SUBDIRMOUNTS ; do
if [ ! -e "$CHROOTORIGINAL/$i" ]; then
>&2 echo "chroot subdir '$CHROOTORIGINAL/$i' not found, rerun dj_make_chroot"
exit 2
fi
done
# This directory is removed at the very end of the debootstrap run, if it's
# still present, building the chroot did not complete.
if [ -d "$CHROOTORIGINAL/debootstrap" ]; then
>&2 echo "chroot dir '$CHROOTORIGINAL' incomplete, rerun dj_make_chroot"
exit 2
fi
# Check that sudo works
TMPDIR="$(mktemp -d)"
cd "$TMPDIR"
mkdir -p dev
if ! sudo -n cp -pR /dev/random /dev/urandom /dev/null dev < /dev/null || [ ! -e dev/null ]; then
>&2 echo "cannot run sudo successfully, check that sudoers file is installed"
rm -rf "$TMPDIR"
exit 2
fi
rm -rf "$TMPDIR"
;;
start)
# Mount (bind) the proc filesystem (needed by Java for /proc/self/stat):
mkdir -p proc
sudo -n mount -n --bind /proc proc < /dev/null
# shellcheck disable=SC2086
for i in $SUBDIRMOUNTS ; do
# Some dirs may be links to others, e.g. /lib64 -> /lib.
# Preserve those; bind mount the others.
if [ -L "$CHROOTORIGINAL/$i" ]; then
ln -s "$(readlink "$CHROOTORIGINAL/$i")" "$i"
elif [ -d "$CHROOTORIGINAL/$i" ]; then
mkdir -p $i
sudo -n mount --bind "$CHROOTORIGINAL/$i" "$i" < /dev/null
# Mount read-only for extra security. Note that this
# must be executed separately from the bind mount.
sudo -n mount -o remount,ro,bind "$PWD/$i" < /dev/null
fi
done
# copy dev/random and /dev/urandom as a random source
mkdir -p dev
sudo -n cp -pR /dev/random /dev/urandom /dev/null dev < /dev/null
sudo -n chmod o-w dev/random dev/urandom < /dev/null
;;
stop)
dj_umount "$PWD/proc"
rm -f dev/urandom dev/random dev/null
rmdir dev || true
for i in $SUBDIRMOUNTS ; do
if [ -L "$CHROOTORIGINAL/$i" ]; then
rm -f "$i"
elif [ -d "$CHROOTORIGINAL/$i" ]; then
dj_umount "$PWD/$i"
fi
done
# KLUDGE: We don't rmdir the empty mountpoint directories, since after
# unmounting, we sometimes still get error messages "Device or
# resource busy" when trying to. This seems only to occur when
# multiple judgedaemons are run on a single host...
;;
*)
echo "Unknown argument '$1' given."
exit 1
esac
exit 0