259 lines
9.5 KiB
Bash
Executable File
259 lines
9.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -eu
|
|
|
|
evidence=${1:?evidence directory is required}
|
|
root=/work/erofs-freebsd-pre
|
|
dut=$root/repo-pre-15
|
|
base=/work/build/vm-freebsd-build.qcow2.bp
|
|
askpass=/work/build/.repo22-ssh-askpass
|
|
module=${B21_MODULE:-$root/planning/pre15/evidence/20260816T-B21-abi15-build/B21-erofs-zstdio0.ko}
|
|
source_tree=${B21_FREEBSD_SRC:-/work/dev-freebsd-releng}
|
|
owned_pid=
|
|
port=
|
|
loaded=0
|
|
mounted=0
|
|
md_units=
|
|
|
|
test ! -e "$evidence"
|
|
mkdir -p "$evidence"
|
|
: >"$evidence/cleanup.log"
|
|
|
|
ssh_args=(env DISPLAY=:0 SSH_ASKPASS="$askpass" SSH_ASKPASS_REQUIRE=force ssh
|
|
-n
|
|
-o BatchMode=no -o PubkeyAuthentication=no
|
|
-o PreferredAuthentications=keyboard-interactive,password
|
|
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
|
-o LogLevel=ERROR -o ConnectTimeout=5)
|
|
scp_args=(env DISPLAY=:0 SSH_ASKPASS="$askpass" SSH_ASKPASS_REQUIRE=force scp
|
|
-O -q -o BatchMode=no -o PubkeyAuthentication=no
|
|
-o PreferredAuthentications=keyboard-interactive,password
|
|
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
|
|
-o LogLevel=ERROR -o ConnectTimeout=5)
|
|
|
|
guest()
|
|
{
|
|
timeout -k 5 60 "${ssh_args[@]}" -p "$port" [email protected] "$@"
|
|
}
|
|
|
|
capture()
|
|
{
|
|
local name=$1
|
|
shift
|
|
set +e
|
|
guest "$@" >"$evidence/$name.stdout" 2>"$evidence/$name.stderr"
|
|
local rc=$?
|
|
set -e
|
|
printf '%s\n' "$rc" >"$evidence/$name.rc"
|
|
}
|
|
|
|
scp_to()
|
|
{
|
|
local source_path=$1
|
|
local destination_path=$2
|
|
timeout -k 5 60 "${scp_args[@]}" -P "$port" "$source_path" \
|
|
"[email protected]:$destination_path"
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
set +e
|
|
local cleanup_rc=0
|
|
if test "$mounted" = 1; then guest umount /mnt/pre15-b21 >>"$evidence/cleanup.log" 2>&1 || cleanup_rc=1; fi
|
|
for md in $md_units; do guest mdconfig -d -u "$md" >>"$evidence/cleanup.log" 2>&1 || cleanup_rc=1; done
|
|
if test "$loaded" = 1; then guest kldunload /root/B21-erofs-zstdio0.ko >>"$evidence/cleanup.log" 2>&1 || cleanup_rc=1; fi
|
|
if test -n "$owned_pid" && kill -0 "$owned_pid" 2>/dev/null; then
|
|
test "$owned_pid" != 26318 || exit 99
|
|
kill "$owned_pid" 2>/dev/null
|
|
wait "$owned_pid" 2>/dev/null
|
|
fi
|
|
test ! -e "$evidence/owned-overlay.qcow2" || unlink "$evidence/owned-overlay.qcow2"
|
|
python3 - "$port" <<'PY'
|
|
import socket
|
|
import sys
|
|
if not sys.argv[1]:
|
|
raise SystemExit(0)
|
|
with socket.socket() as sock:
|
|
sock.settimeout(0.2)
|
|
raise SystemExit(0 if sock.connect_ex(("127.0.0.1", int(sys.argv[1]))) else 1)
|
|
PY
|
|
test $? = 0 || cleanup_rc=1
|
|
stat -c 'path=%n size=%s inode=%i mode=%f mtime=%Y ctime=%Z' "$base" \
|
|
>"$evidence/base-metadata-after.txt"
|
|
cmp -s "$evidence/base-metadata-before.txt" "$evidence/base-metadata-after.txt" || cleanup_rc=1
|
|
if test "$cleanup_rc" = 0 && test ! -e "$evidence/owned-overlay.qcow2"; then
|
|
printf '%s\n' PASS >"$evidence/cleanup.status"
|
|
else
|
|
printf '%s\n' FAIL >"$evidence/cleanup.status"
|
|
fi
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
test -x "$askpass"
|
|
test -f "$module"
|
|
test -f "$base"
|
|
stat -c 'path=%n size=%s inode=%i mode=%f mtime=%Y ctime=%Z' "$base" \
|
|
>"$evidence/base-metadata-before.txt"
|
|
git -C "$dut" rev-parse HEAD >"$evidence/dut-head.txt"
|
|
{
|
|
git -C "$source_tree" log -1 --format='%H %cs %s'
|
|
sed -n '76,77p' "$source_tree/sys/sys/param.h"
|
|
sed -n '53,54p' "$source_tree/sys/conf/newvers.sh"
|
|
} >"$evidence/source-identity.txt"
|
|
printf '%s\n' 'SSH options precede [email protected] and the remote command' \
|
|
>"$evidence/transport-contract.txt"
|
|
|
|
python3 -B "$dut/tests/pre15/fixtures/B21-super-generate.py" \
|
|
--spec "$dut/tests/pre15/fixtures/B21-super-spec.json" \
|
|
--output "$evidence/first" --work "$evidence/first-work" \
|
|
>"$evidence/generate-first.stdout" 2>"$evidence/generate-first.stderr"
|
|
python3 -B "$dut/tests/pre15/fixtures/B21-super-generate.py" \
|
|
--spec "$dut/tests/pre15/fixtures/B21-super-spec.json" \
|
|
--output "$evidence/second" --work "$evidence/second-work" \
|
|
>"$evidence/generate-second.stdout" 2>"$evidence/generate-second.stderr"
|
|
cmp "$evidence/first/fixture-index.json" "$evidence/second/fixture-index.json"
|
|
python3 -B "$dut/tests/pre15/fixtures/B21-super-oracle.py" \
|
|
--fixtures "$evidence/first" --report "$evidence/oracle.json" \
|
|
>"$evidence/oracle.stdout" 2>"$evidence/oracle.stderr"
|
|
|
|
python3 - "$evidence/first/fixture-index.json" "$evidence/oracle.json" \
|
|
"$evidence/matrix.tsv" <<'PY'
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
index = json.loads(Path(sys.argv[1]).read_text())
|
|
oracle = json.loads(Path(sys.argv[2]).read_text())
|
|
assert index["case_count"] == 13 and oracle["passed_count"] == 13
|
|
rows = ["id\texpected_errno\treject"]
|
|
for fixture, result in zip(index["cases"], oracle["results"], strict=True):
|
|
rows.append(
|
|
f"{fixture['id']}\t{result['actual_errno']}\t"
|
|
f"{fixture['expected_reject']}"
|
|
)
|
|
Path(sys.argv[3]).write_text("\n".join(rows) + "\n")
|
|
PY
|
|
tar -C "$evidence/first" -czf "$evidence/fixtures.tar.gz" .
|
|
|
|
qemu-img create -f qcow2 -F qcow2 -b "$base" \
|
|
"$evidence/owned-overlay.qcow2" >"$evidence/qemu-img.stdout" \
|
|
2>"$evidence/qemu-img.stderr"
|
|
port=$(python3 - <<'PY'
|
|
import socket
|
|
with socket.socket() as sock:
|
|
sock.bind(("127.0.0.1", 0))
|
|
port = sock.getsockname()[1]
|
|
if port == 9222:
|
|
raise SystemExit("protected port selected")
|
|
print(port)
|
|
PY
|
|
)
|
|
printf '%s\n' "$port" >"$evidence/owned-port.txt"
|
|
qemu-system-x86_64 -accel tcg,thread=multi -cpu qemu64 -m 6144 -smp 4 \
|
|
-drive "file=$evidence/owned-overlay.qcow2,if=virtio,format=qcow2" \
|
|
-netdev "user,id=net0,hostfwd=tcp:127.0.0.1:$port-:22" \
|
|
-device virtio-net-pci,netdev=net0 -display none \
|
|
-serial "file:$evidence/serial.log" -monitor none \
|
|
>"$evidence/qemu.stdout" 2>"$evidence/qemu.stderr" &
|
|
owned_pid=$!
|
|
printf '%s\n' "$owned_pid" >"$evidence/owned-pid.txt"
|
|
test "$owned_pid" != 26318
|
|
|
|
ready=0
|
|
for attempt in $(seq 1 180); do
|
|
if ! kill -0 "$owned_pid" 2>/dev/null; then exit 21; fi
|
|
set +e
|
|
guest true >"$evidence/readiness.stdout" 2>"$evidence/readiness.stderr"
|
|
readiness_rc=$?
|
|
set -e
|
|
printf '%s\n' "$readiness_rc" >"$evidence/readiness.rc"
|
|
if test "$readiness_rc" = 0; then ready=1; break; fi
|
|
sleep 1
|
|
done
|
|
printf 'attempts=%s ready=%s\n' "$attempt" "$ready" >"$evidence/readiness.txt"
|
|
test "$ready" = 1
|
|
|
|
capture guest-uname uname -a
|
|
capture guest-freebsd-version freebsd-version -kru
|
|
capture guest-osreldate sysctl -n kern.osreldate
|
|
capture guest-kldstat-before kldstat
|
|
capture guest-kldstat-module-before kldstat -q -m erofs
|
|
capture guest-dmesg-before dmesg
|
|
test "$(cat "$evidence/guest-kldstat-module-before.rc")" = 1
|
|
|
|
scp_to "$module" /root/B21-erofs-zstdio0.ko \
|
|
>"$evidence/upload-module.stdout" 2>"$evidence/upload-module.stderr"
|
|
scp_to "$dut/tests/pre15/fixtures/B21-qemu-probe.c" /root/B21-qemu-probe.c \
|
|
>"$evidence/upload-probe.stdout" 2>"$evidence/upload-probe.stderr"
|
|
scp_to "$evidence/fixtures.tar.gz" /root/B21-fixtures.tar.gz \
|
|
>"$evidence/upload-fixtures.stdout" 2>"$evidence/upload-fixtures.stderr"
|
|
capture guest-module-file file /root/B21-erofs-zstdio0.ko
|
|
capture guest-module-sha256 sha256 -q /root/B21-erofs-zstdio0.ko
|
|
capture guest-prepare sh -c \
|
|
'rm -rf /root/B21-fixtures /mnt/pre15-b21; mkdir /root/B21-fixtures /mnt/pre15-b21; tar -xzf /root/B21-fixtures.tar.gz -C /root/B21-fixtures; cc -O2 -Wall -Wextra -Werror -std=c17 -o /root/B21-qemu-probe /root/B21-qemu-probe.c'
|
|
test "$(cat "$evidence/guest-prepare.rc")" = 0
|
|
|
|
capture B21-kldload kldload /root/B21-erofs-zstdio0.ko
|
|
test "$(cat "$evidence/B21-kldload.rc")" = 0
|
|
loaded=1
|
|
capture guest-kldstat-after-load kldstat
|
|
capture guest-kldstat-module-after-load kldstat -q -m erofs
|
|
capture guest-dmesg-after-load dmesg
|
|
test "$(cat "$evidence/guest-kldstat-module-after-load.rc")" = 0
|
|
|
|
printf 'id\texpected_errno\tactual_errno\treject\n' \
|
|
>"$evidence/qemu-matrix.tsv"
|
|
while IFS="$(printf '\t')" read -r id expected_errno reject; do
|
|
test "$id" != id || continue
|
|
set +e
|
|
md=$(guest mdconfig -a -t vnode -f "/root/B21-fixtures/$id.erofs" \
|
|
2>"$evidence/$id-md.stderr")
|
|
md_rc=$?
|
|
set -e
|
|
printf '%s\n' "$md_rc" >"$evidence/$id-md.rc"
|
|
test "$md_rc" = 0
|
|
md_units="$md_units $md"
|
|
set +e
|
|
probe_result=$(guest /root/B21-qemu-probe "/dev/$md" /mnt/pre15-b21 \
|
|
2>"$evidence/$id-probe.stderr")
|
|
probe_rc=$?
|
|
set -e
|
|
printf '%s\n' "$probe_rc" >"$evidence/$id-probe.rc"
|
|
printf '%s\n' "$probe_result" >"$evidence/$id-probe.stdout"
|
|
actual_errno=$(printf '%s\n' "$probe_result" | \
|
|
sed -n 's/.*errno=\([0-9][0-9]*\).*/\1/p')
|
|
test -n "$actual_errno"
|
|
printf '%s\t%s\t%s\t%s\n' "$id" "$expected_errno" "$actual_errno" \
|
|
"$reject" >>"$evidence/qemu-matrix.tsv"
|
|
test "$actual_errno" = "$expected_errno"
|
|
if test "$actual_errno" = 0; then
|
|
mounted=1
|
|
guest find /mnt/pre15-b21 -mindepth 1 -maxdepth 1 -print \
|
|
>"$evidence/$id-readdir.txt"
|
|
guest umount /mnt/pre15-b21
|
|
mounted=0
|
|
fi
|
|
guest mdconfig -d -u "$md"
|
|
md_units=$(printf '%s\n' "$md_units" | sed "s/ $md//")
|
|
done <"$evidence/matrix.tsv"
|
|
|
|
capture guest-dmesg-after dmesg
|
|
capture guest-kldstat-after kldstat
|
|
capture guest-kldstat-module-after kldstat -q -m erofs
|
|
diff -u "$evidence/guest-dmesg-before.stdout" \
|
|
"$evidence/guest-dmesg-after.stdout" >"$evidence/dmesg.diff" || true
|
|
if grep -Eqi 'panic:|lock order reversal|witness.*warning|use-after-free' \
|
|
"$evidence/dmesg.diff"; then
|
|
exit 10
|
|
fi
|
|
guest kldunload /root/B21-erofs-zstdio0.ko >"$evidence/guest-kldunload.stdout" \
|
|
2>"$evidence/guest-kldunload.stderr"
|
|
loaded=0
|
|
capture guest-kldstat-module-clean kldstat -q -m erofs
|
|
capture guest-mount-clean mount -p
|
|
capture guest-md-clean mdconfig -l
|
|
test "$(cat "$evidence/guest-kldstat-module-clean.rc")" = 1
|
|
test ! -s "$evidence/guest-md-clean.stdout"
|
|
test -z "$(awk '$3 == "erofs" { print }' "$evidence/guest-mount-clean.stdout")"
|
|
printf '%s\n' reached >"$evidence/target.marker"
|
|
printf '%s\n' 'B21_PASS TC172-super-trust 13/13' >"$evidence/RESULT.txt"
|