diff --git a/judge/runguard.cc b/judge/runguard.cc index 7bbcf50c1e..58a1ed9bda 100644 --- a/judge/runguard.cc +++ b/judge/runguard.cc @@ -806,6 +806,8 @@ void setrestrictions() /* Set additional environment variables. */ for (const auto &tokens : environment_variables) { + // Note that we explicitly *do not* free the string created by + // strdup as putenv does not copy that string, but uses it as is. char *token = strtok(strdup(tokens.c_str()), ";"); while (token != nullptr) { verbose("setting environment variable: %s", token); diff --git a/judge/runguard_test/runguard_test.sh b/judge/runguard_test/runguard_test.sh index a8428ad4b4..c21d1a3739 100755 --- a/judge/runguard_test/runguard_test.sh +++ b/judge/runguard_test/runguard_test.sh @@ -5,6 +5,7 @@ cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1 RUNGUARD=../runguard +RUNGUARD_OPTIONS='-u domjudge-run-0' LOG1="$(mktemp)" LOG2="$(mktemp)" # shellcheck disable=SC2154 @@ -66,39 +67,39 @@ test_no_sudo() { } test_ls() { - exec_check_success sudo $RUNGUARD -u domjudge-run-0 ls + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS ls expect_stdout "runguard_test.sh" } test_walltime_limit() { - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -t 2 sleep 1 + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -t 2 sleep 1 - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -t 2 sleep 3 + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -t 2 sleep 3 expect_stderr "timelimit exceeded" expect_stderr "hard wall time" } test_cputime_limit() { # 2 threads, ~3s of CPU time, gives ~1.5s of wall time. - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -C 3.1 ./threads 2 3 + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -C 3.1 ./threads 2 3 # Now also limiting wall time to 2s. - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -C 3.1 -t 2 ./threads 2 3 + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -C 3.1 -t 2 ./threads 2 3 # Some failing cases. - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -C 2.9 ./threads 2 3 - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -C 3.1 -t 1.4 ./threads 2 3 + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -C 2.9 ./threads 2 3 + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -C 3.1 -t 1.4 ./threads 2 3 } test_cputime_pinning() { # 2 threads, ~3s of CPU time, with one core we are out of luck... - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -C 3.1 -t 2 -P 1 ./threads 2 3 + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -C 3.1 -t 2 -P 1 ./threads 2 3 # ...but with two cores it works. - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -C 3.1 -t 2 -P 0-1 ./threads 2 3 + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -C 3.1 -t 2 -P 0-1 ./threads 2 3 } test_streamsize() { - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -t 1 -s 123 yes DOMjudge + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -t 1 -s 123 yes DOMjudge expect_stdout "DOMjudge" limit=$((123*1024)) actual=$(wc -c < "$LOG1") @@ -106,7 +107,7 @@ test_streamsize() { } test_streamsize_stderr() { - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -t 1 -s 42 ./fill-stderr.sh + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -t 1 -s 42 ./fill-stderr.sh expect_stderr "DOMjudge" # Allow 100 bytes extra, for the runguard time limit message. limit=$((42*1024 + 100)) @@ -119,15 +120,15 @@ test_redir_stdout() { chmod go+rwx "$stdout" # Basic test. - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -o "$stdout" echo 'foobar' + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -o "$stdout" echo 'foobar' grep -q "foobar" "$stdout" || fail "did not find expected 'foobar' in redirect stdout" - + # Verify that stdout is empty. actual=$(wc -c < "$LOG1") [ $actual -eq 0 ] || fail "stdout should be empty, but contains ${actual}B" # This will fail because of the timeout. - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -t 1 -s 23 -o "$stdout" yes DOMjudge + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -t 1 -s 23 -o "$stdout" yes DOMjudge expect_stderr "timelimit exceeded" expect_stderr "hard wall time" @@ -149,7 +150,7 @@ test_redir_stderr() { chmod go+rwx "$stderr" # This will fail because of the timeout. - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -t 1 -s 11 -e "$stderr" ./fill-stderr.sh + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -t 1 -s 11 -e "$stderr" ./fill-stderr.sh expect_stderr "timelimit exceeded" expect_stderr "hard wall time" @@ -173,47 +174,47 @@ test_rootdir_changedir() { cp hello "$almost_empty_dir"/ ln -sf /hello "$almost_empty_dir"/exists/foo - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -r "$almost_empty_dir" ./hello + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -r "$almost_empty_dir" ./hello expect_stdout "Hello DOMjudge" - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -r "$almost_empty_dir" -d doesnotexist /hello + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -r "$almost_empty_dir" -d doesnotexist /hello expect_stderr "cannot chdir to \`doesnotexist' in chroot" - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -r "$almost_empty_dir" -d exists /hello + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -r "$almost_empty_dir" -d exists /hello expect_stdout "Hello DOMjudge" - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -r "$almost_empty_dir" -d exists ./foo + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -r "$almost_empty_dir" -d exists ./foo expect_stdout "Hello DOMjudge" - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -r "$almost_empty_dir" -d exists /exists/foo + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -r "$almost_empty_dir" -d exists /exists/foo expect_stdout "Hello DOMjudge" } test_memsize() { # This is slightly over the limit as there is other stuff to be allocated as well. - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -m 1024 ./mem $((1024*1024)) + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -m 1024 ./mem $((1024*1024)) - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -m 1500 ./mem $((1024*1024)) + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -m 1500 ./mem $((1024*1024)) expect_stdout "mem = 1048576" - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -m $((1024*1024)) ./mem $((1024*1024*1024)) - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -m $((1024*1024 + 10000)) ./mem $((1024*1024*1024)) + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -m $((1024*1024)) ./mem $((1024*1024*1024)) + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -m $((1024*1024 + 10000)) ./mem $((1024*1024*1024)) expect_stdout "mem = 1073741824" } test_envvars() { - exec_check_success sudo $RUNGUARD -u domjudge-run-0 ./print_envvars.py + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS ./print_envvars.py expect_stdout "COUNT: 2." expect_stdout "PATH=" expect_stdout "LC_CTYPE=" not_expect_stdout "DOMjudge" - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -E ./print_envvars.py + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -E ./print_envvars.py expect_stdout "HOME=" expect_stdout "USER=" expect_stdout "SHELL=" - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -V"DOMjudgeA=A;DOMjudgeB=BB" -V"DOMjudgeC=CCC" ./print_envvars.py + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -V"DOMjudgeA=A;DOMjudgeB=BB" -V"DOMjudgeC=CCC" ./print_envvars.py expect_stdout "COUNT: 5." expect_stdout "DOMjudgeA=A" expect_stdout "DOMjudgeB=BB" @@ -224,10 +225,10 @@ test_envvars() { } test_nprocs() { - exec_check_success sudo $RUNGUARD -u domjudge-run-0 ./forky.sh + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS ./forky.sh expect_stdout 31 - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -p 16 ./forky.sh + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -p 16 ./forky.sh expect_stdout 15 not_expect_stdout 16 not_expect_stdout 31 @@ -235,7 +236,7 @@ test_nprocs() { } test_meta() { - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -t 2 -M "$META" sleep 1 + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -t 2 -M "$META" sleep 1 expect_meta 'wall-time: 1.0' expect_meta 'cpu-time: 0.0' expect_meta 'sys-time: 0.0' @@ -245,27 +246,27 @@ test_meta() { expect_meta 'stdout-bytes: 0' expect_meta 'stderr-bytes: 0' - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -M "$META" false + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -M "$META" false expect_meta 'exitcode: 1' # shellcheck disable=SC2024 - echo "DOMjudge" | sudo $RUNGUARD -u domjudge-run-0 -t 2 -M "$META" rev > "$LOG1" 2> "$LOG2" + echo "DOMjudge" | sudo $RUNGUARD $RUNGUARD_OPTIONS -t 2 -M "$META" rev > "$LOG1" 2> "$LOG2" expect_meta 'wall-time: 0.0' expect_meta 'stdout-bytes: 9' expect_stdout "egdujMOD" - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -C 3.1 -t 1.4 -M "$META" ./threads 2 3 + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -C 3.1 -t 1.4 -M "$META" ./threads 2 3 expect_meta 'exitcode: 143' expect_meta 'signal: 14' expect_meta 'wall-time: 1.5' expect_meta 'time-result: hard-timelimit' - exec_check_success sudo $RUNGUARD -u domjudge-run-0 -C 1:5 -M "$META" ./threads 2 3 + exec_check_success sudo $RUNGUARD $RUNGUARD_OPTIONS -C 1:5 -M "$META" ./threads 2 3 expect_meta 'time-used: cpu-time' expect_meta 'time-result: soft-timelimit' expect_meta 'exitcode: 0' - exec_check_fail sudo $RUNGUARD -u domjudge-run-0 -t 1 -s 3 -M "$META" ./fill-stderr.sh + exec_check_fail sudo $RUNGUARD $RUNGUARD_OPTIONS -t 1 -s 3 -M "$META" ./fill-stderr.sh # We expect stderr-bytes to have a non-zero value. expect_meta 'stderr-bytes: ' grep -q 'stderr-bytes: 0' "$META" && fail ""