### Variant A: fs_ncg=-1 (bzero(-1) write primitive) ### === kernel size arithmetic (int size) === fs_ncg = -1 (0xffffffff) fs_cssize = 2048 fs_contigsumsize = 7 fs_fsize = 2048 size after L680 = 2048 size after L683 = 2044 (fs_ncg*4 product as int) size after L684 = 2043 <-- passed to kmalloc as (u_long) kmalloc((u_long)size) -> kmalloc(2043) bytes blks (howmany(cssize,fsize)) = 1 [maxcluster loop L703-704] guard i bzero writes 4294967295 bytes; OVERFLOWS kmalloc(2043) by 4294965252 bytes -> heap corruption >>> UNBOUNDED WRITE: kernel bzero runs until it page-faults on an unmapped page -> deterministic panic (DoS). Synchronous in the mount syscall; no return to userspace -> no clean LPE conversion. ### Variant B: fs_ncg=858993460 (maxcluster controlled-value overflow) ### === kernel size arithmetic (int size) === fs_ncg = 858993460 (0x33333334) fs_cssize = 2048 fs_contigsumsize = 7 fs_fsize = 2048 size after L680 = 2048 size after L683 = -858991408 (fs_ncg*4 product as int) size after L684 = 2052 <-- passed to kmalloc as (u_long) kmalloc((u_long)size) -> kmalloc(2052) bytes blks (howmany(cssize,fsize)) = 1 [maxcluster loop L703-704] guard i OVERFLOWS the kmalloc region -> controlled-value HEAP CORRUPTION [bzero L707-709] size = fs_ncg*1 = 858993460 (int); bzero(ptr, (u_long)858993460) = bzero 858993460 bytes -> bzero writes 858993460 bytes; OVERFLOWS kmalloc(2052) by 858991408 bytes -> heap corruption >>> UNBOUNDED WRITE: kernel bzero runs until it page-faults on an unmapped page -> deterministic panic (DoS). Synchronous in the mount syscall; no return to userspace -> no clean LPE conversion. ### Variant C: fs_fsize=0 (div-by-zero) ### === kernel size arithmetic (int size) === fs_ncg = 1 (0x00000001) fs_cssize = 2048 fs_contigsumsize = 7 fs_fsize = 0 size after L680 = 2048 size after L683 = 2052 (fs_ncg*4 product as int) size after L684 = 2053 <-- passed to kmalloc as (u_long) kmalloc((u_long)size) -> kmalloc(2053) bytes blks (howmany(cssize,fsize)) = 0 [maxcluster loop L703-704] guard i fits in kmalloc -> no overflow [bzero L707-709] size = fs_ncg*1 = 1 (int); bzero(ptr, (u_long)1) = bzero 1 bytes -> bzero writes 1 bytes; fits within kmalloc(2053) ### Sanity: normal fs_ncg=1 ### === kernel size arithmetic (int size) === fs_ncg = 1 (0x00000001) fs_cssize = 2048 fs_contigsumsize = 7 fs_fsize = 2048 size after L680 = 2048 size after L683 = 2052 (fs_ncg*4 product as int) size after L684 = 2053 <-- passed to kmalloc as (u_long) kmalloc((u_long)size) -> kmalloc(2053) bytes blks (howmany(cssize,fsize)) = 1 [maxcluster loop L703-704] guard i fits in kmalloc -> no overflow [bzero L707-709] size = fs_ncg*1 = 1 (int); bzero(ptr, (u_long)1) = bzero 1 bytes -> bzero writes 1 bytes; fits within kmalloc(2053)