update
This commit is contained in:
Executable
+228
@@ -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'
|
||||
Reference in New Issue
Block a user