This commit is contained in:
2026-08-18 09:20:44 +02:00
commit b826cd721a
522 changed files with 93730 additions and 0 deletions
+228
View File
@@ -0,0 +1,228 @@
#!/bin/sh
set -eu
dut=${1:?DUT path is required}
freebsd_src=${2:?FreeBSD source path is required}
base=${3:?base image is required}
askpass=${4:?askpass path is required}
output=${5:?output path is required}
protected_pid=26318
protected_port=9222
builder=$dut/tests/pre15/fixtures/B12-build-kld.sh
test ! -e "$output" || {
printf '%s\n' "B12 QEMU output exists: $output" >&2
exit 20
}
mkdir -p "$output"
work=$(mktemp -d /tmp/pre15-b12-qemu.XXXXXX)
overlay=$work/guest-overlay.qcow2
module=$work/B12-erofs-zstdio0.ko
qemu_pid=
port=
guest_ready=0
module_loaded=0
protected_start=$(awk '{print $22}' /proc/$protected_pid/stat)
protected_cmd=$(sha256sum /proc/$protected_pid/cmdline | awk '{print $1}')
stat -c 'path=%n size=%s inode=%i mode=%f mtime=%Y ctime=%Z' "$base" \
>"$output/base-metadata-before.txt"
ssh_options()
{
printf '%s\n' \
-q \
-o BatchMode=no \
-o PubkeyAuthentication=no \
-o PreferredAuthentications=keyboard-interactive,password \
-o NumberOfPasswordPrompts=1 \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=5 \
-p "$port"
}
guest()
{
timeout -k 5 "${B12_GUEST_TIMEOUT:-60}" env DISPLAY=:0 \
SSH_ASKPASS="$askpass" SSH_ASKPASS_REQUIRE=force \
ssh $(ssh_options) [email protected] "$@"
}
copy_to_guest()
{
timeout -k 5 "${B12_COPY_TIMEOUT:-120}" 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 NumberOfPasswordPrompts=1 \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=5 \
-P "$port" "$1" [email protected]:"$2"
}
port_free()
{
python3 - "$1" <<'PY'
import socket
import sys
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(0.2)
raise SystemExit(0 if sock.connect_ex(("127.0.0.1", int(sys.argv[1]))) != 0 else 1)
PY
}
cleanup()
{
set +e
if test "$guest_ready" = 1 && test "$module_loaded" = 1; then
guest kldunload /root/B12-erofs-zstdio0.ko \
>>"$output/cleanup.log" 2>&1
module_loaded=0
fi
if test -n "$qemu_pid" && kill -0 "$qemu_pid" 2>/dev/null; then
kill -TERM "$qemu_pid" 2>/dev/null
wait_count=0
while kill -0 "$qemu_pid" 2>/dev/null && test "$wait_count" -lt 20; do
sleep 1
wait_count=$((wait_count + 1))
done
if kill -0 "$qemu_pid" 2>/dev/null; then
kill -KILL "$qemu_pid" 2>/dev/null
fi
wait "$qemu_pid" 2>/dev/null
fi
rm -rf "$work"
}
trap cleanup EXIT HUP INT TERM
for tool in awk clang file nm python3 qemu-img qemu-system-x86_64 scp \
sha256sum ssh stat timeout; do
command -v "$tool" >/dev/null 2>&1 || {
printf '%s\n' "missing B12 QEMU tool: $tool" >&2
exit 21
}
done
test -d "$freebsd_src/sys"
test -f "$base"
test -x "$askpass"
test -r /proc/$protected_pid/stat
timeout -k 10 600 /bin/sh "$builder" "$dut" "$freebsd_src" "$module" \
"$work/kld-work" >"$output/build.stdout" 2>"$output/build.stderr"
file "$module" >"$output/module.file"
sha256sum "$module" >"$output/module.sha256"
nm -g "$module" | LC_ALL=C sort >"$output/module.nm-global"
nm -u "$module" | LC_ALL=C sort >"$output/module.nm-u"
qemu-img create -q -f qcow2 -F qcow2 -b "$base" "$overlay"
port=$(python3 - "$protected_port" <<'PY'
import socket
import sys
protected = int(sys.argv[1])
while True:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind(("127.0.0.1", 0))
port = sock.getsockname()[1]
if port != protected:
print(port)
break
PY
)
printf '%s\n' "$port" >"$output/owned-port.txt"
qemu-system-x86_64 -accel tcg,thread=multi -cpu qemu64 \
-m 3072 -smp 2 \
-drive "file=$overlay,if=virtio,format=qcow2,cache=none" \
-netdev "user,id=net0,hostfwd=tcp:127.0.0.1:$port-:22" \
-device virtio-net-pci,netdev=net0 -display none \
-serial "file:$output/serial.log" -monitor none \
-D "$output/qemu.log" >"$output/qemu-process.log" 2>&1 &
qemu_pid=$!
printf '%s\n' "$qemu_pid" >"$output/owned-pid.txt"
printf '%s\n' \
"qemu-system-x86_64 -m 3072 -smp 2 -drive owned-overlay -port $port" \
>"$output/qemu-argv-summary.txt"
boot_wait=0
while test "$boot_wait" -lt "${B12_BOOT_TIMEOUT:-300}"; do
if ! kill -0 "$qemu_pid" 2>/dev/null; then
printf '%s\n' 'owned QEMU exited before SSH readiness' >&2
exit 21
fi
if B12_GUEST_TIMEOUT=10 guest true >/dev/null 2>&1; then
guest_ready=1
break
fi
sleep 2
boot_wait=$((boot_wait + 2))
done
test "$guest_ready" = 1 || {
printf '%s\n' 'owned QEMU SSH boot deadline expired' >&2
exit 21
}
guest uname -a >"$output/guest-uname.txt"
guest sysctl -n kern.osreldate >"$output/guest-osreldate.txt"
test "$(tr -d '\r\n' < "$output/guest-osreldate.txt")" = 1500068 || {
printf '%s\n' 'guest OSREL is not exact FreeBSD 15 ABI 1500068' >&2
exit 10
}
if guest kldstat -q -m erofs >/dev/null 2>&1; then
printf '%s\n' 'guest already has an EROFS module loaded' >&2
exit 21
fi
copy_to_guest "$module" /root/B12-erofs-zstdio0.ko
guest sha256 -q /root/B12-erofs-zstdio0.ko >"$output/guest-module.sha256"
test "$(awk '{print $1}' "$output/module.sha256")" = \
"$(tr -d '\r\n' < "$output/guest-module.sha256")"
guest dmesg >"$output/dmesg-before.txt"
guest kldload /root/B12-erofs-zstdio0.ko >"$output/kldload.stdout" \
2>"$output/kldload.stderr"
module_loaded=1
guest kldstat -n B12-erofs-zstdio0.ko >"$output/kldstat-loaded.txt"
guest kldunload /root/B12-erofs-zstdio0.ko >"$output/kldunload.stdout" \
2>"$output/kldunload.stderr"
module_loaded=0
guest dmesg >"$output/dmesg-after.txt"
diff -u "$output/dmesg-before.txt" "$output/dmesg-after.txt" \
>"$output/dmesg.diff" || true
sed -n '/^+++ /d; /^+/s/^+//p' "$output/dmesg.diff" \
>"$output/dmesg-added.txt"
if grep -Eqi 'panic:|lock order reversal|witness.*warning|use-after-free|link_elf_obj: symbol .* undefined' \
"$output/dmesg-added.txt"; then
printf '%s\n' 'B12 exact-ABI load produced a kernel diagnostic' >&2
exit 10
fi
cleanup
trap - EXIT HUP INT TERM
stat -c 'path=%n size=%s inode=%i mode=%f mtime=%Y ctime=%Z' "$base" \
>"$output/base-metadata-after.txt"
cmp "$output/base-metadata-before.txt" "$output/base-metadata-after.txt"
test -r /proc/$protected_pid/stat
test "$(awk '{print $22}' /proc/$protected_pid/stat)" = "$protected_start"
test "$(sha256sum /proc/$protected_pid/cmdline | awk '{print $1}')" = "$protected_cmd"
port_free "$port"
cat >"$output/result.json" <<EOF
{
"candidate": "P15-087",
"exact_abi_osreldate": 1500068,
"kld_load": "PASS",
"kld_unload": "PASS",
"kernel_log": "PASS",
"owned_overlay_removed": true,
"owned_pid_stopped": true,
"owned_port": $port,
"owned_port_free_after": true,
"protected_pid": $protected_pid,
"protected_port": $protected_port,
"schema": 1,
"status": "PASS"
}
EOF
printf '%s\n' 'B12 exact-ABI QEMU load/unload PASS'