DragonFlyBSD Kernel Audit
DF-0807 / phase8_validate.sh
← back to finding ↓ download raw
#!/bin/sh
# Phase 8 validation for DF-0807.
#
# dirfs is vkernel64-only (sys/platform/vkernel64/conf/files), so it is NOT
# in the running X86_64_GENERIC host kernel -- a live boot test of the fix
# is impossible on this guest (no vkernel runs here). We validate the fix
# to the maximum extent possible:
#
#   (1) git apply --check passes on a clean tree (host-side, done separately).
#   (2) Apply the fix to /usr/src/sys/vfs/dirfs/dirfs_vnops.c.
#   (3) Compile-neutrality: compile dirfs_vnops.c PATCHED vs UNPATCHED with
#       kernel build flags derived from a configured VKERNEL64_DIRFS kernel
#       (the obj dir's `machine`/`machine_base` symlinks resolve <machine/*>
#       to the vkernel64 platform headers, not the userland pc64 ones). The
#       fix (deleting one line) must introduce ZERO new compile errors.
#       dirfs_vnops.c omits some includes that sibling dirfs_vfsops.c has,
#       so both PATCHED and UNPATCHED fail with the SAME pre-existing error
#       set (kmalloc/kfree/M_WAITOK/M_ZERO undeclared). We diff the two
#       error outputs to prove the fix adds nothing new.
#   (4) The harness FIXED transcription deterministically shows no OOB
#       across all tested buffer sizes (already proven in run.log).

set -e

echo "=== DF-0807 Phase 8 fix validation ==="
date

OBJ=/usr/src/sys/platform/vkernel64/compile/VKERNEL64_DIRFS

# ---------------------------------------------------------------- (0) config
echo
echo "=== (0) set up kernel include aliases for <machine/*> ============="
# The config-generated obj dir symlinks can be mis-nested when the obj is not
# at /usr/obj/usr/src/sys/$K. We build our own correct `machine` alias so
# <machine/smp.h> resolves to the VKERNEL64 platform header (not the userland
# pc64 one that pulls in machine_base/apic/apicreg.h).
KERNINC=/tmp/kerninc
rm -rf $KERNINC && mkdir -p $KERNINC
ln -sf /usr/src/sys/platform/vkernel64/include $KERNINC/machine
echo "machine alias: $KERNINC/machine -> $(readlink $KERNINC/machine)"
ls -la $KERNINC/machine/smp.h >/dev/null 2>&1 && echo "vkernel64 smp.h reachable" || echo "WARN: smp.h not reachable"

CFLAGS="-c -O2 -pipe -DNDEBUG -D_KERNEL"
# /tmp/kerninc FIRST so <machine/*> finds the vkernel64 platform headers
INC="-I$KERNINC -I/usr/src/sys/platform/vkernel64/include -I/usr/src/sys -I/usr/src"

# ---------------------------------------------------------------- (2) apply
echo
echo "=== (2) apply fix.diff to /usr/src ==="
cp /root/fix.diff /tmp/fix.diff
cd /usr/src
patch -p1 --forward < /tmp/fix.diff 2>&1 || true
echo "--- patched region (lines 1277-1286) ---"
sed -n '1277,1286p' sys/vfs/dirfs/dirfs_vnops.c

# ---------------------------------------------------------------- (3b) patched compile
echo
echo "=== (3b) compile PATCHED dirfs_vnops.c ==="
PATCHED_LOG=/tmp/dirfs_vnops.patched.log
cc $CFLAGS $INC /usr/src/sys/vfs/dirfs/dirfs_vnops.c -o /tmp/dirfs_vnops.patched.o 2> $PATCHED_LOG || true
echo "--- PATCHED compile errors (sorted unique) ---"
grep -E "error:" $PATCHED_LOG | sort -u || echo "(none)"
echo "--- error count: $(grep -cE 'error:' $PATCHED_LOG || echo 0) ---"

# ---------------------------------------------------------------- (3c) revert + unpatched compile
echo
echo "=== (3c) revert fix, compile UNPATCHED dirfs_vnops.c ==="
cd /usr/src
patch -p1 -R --forward < /tmp/fix.diff 2>&1 || true
echo "--- unpatched region (lines 1277-1286) ---"
sed -n '1277,1286p' sys/vfs/dirfs/dirfs_vnops.c

UNPATCHED_LOG=/tmp/dirfs_vnops.unpatched.log
cc $CFLAGS $INC /usr/src/sys/vfs/dirfs/dirfs_vnops.c -o /tmp/dirfs_vnops.unpatched.o 2> $UNPATCHED_LOG || true
echo "--- UNPATCHED compile errors (sorted unique) ---"
grep -E "error:" $UNPATCHED_LOG | sort -u || echo "(none)"
echo "--- error count: $(grep -cE 'error:' $UNPATCHED_LOG || echo 0) ---"

# ---------------------------------------------------------------- (3d) diff
echo
echo "=== (3d) error-set diff (PATCHED vs UNPATCHED) ==="
grep -E "error:" $PATCHED_LOG   | sort -u > /tmp/p.err
grep -E "error:" $UNPATCHED_LOG | sort -u > /tmp/u.err
if diff /tmp/p.err /tmp/u.err > /tmp/pu.diff; then
    echo "IDENTICAL error sets -- fix introduces ZERO new compile errors"
else
    echo "DIFFERENT error sets:"
    cat /tmp/pu.diff
fi
echo "--- line counts: patched=$(wc -l < /tmp/p.err) unpatched=$(wc -l < /tmp/u.err) ---"

# ---------------------------------------------------------------- (3e) reapply
echo
echo "=== (3e) re-apply fix to leave /usr/src patched ==="
cd /usr/src
if sed -n '1283,1285p' sys/vfs/dirfs/dirfs_vnops.c | grep -q 'dp = dpn'; then
    echo "fix NOT applied -- applying now"
    patch -p1 --forward < /tmp/fix.diff 2>&1 | tail -3
else
    echo "fix already applied (content check)"
fi
echo "--- final patched region (lines 1277-1286) ---"
sed -n '1277,1286p' sys/vfs/dirfs/dirfs_vnops.c
echo "--- content verification: 'dp = dpn' in loop body? ---"
if sed -n '1283,1285p' sys/vfs/dirfs/dirfs_vnops.c | grep -q 'dp = dpn'; then
    echo "STILL PRESENT (re-apply FAILED)"
else
    echo "ABSENT (fix correctly applied)"
fi

echo
echo "=== Phase 8 done ==="
date