DF-2552 / run.log
DF-2552: sbuf_extend / sbuf_extendsize int-truncation proof ============================================================= === Normal: s_size=16, addlen=1 (sbuf_put_byte path) === s_size (ssize_t) = 16 addlen (int) = 1 s_size + addlen = 17 (as ssize_t, no overflow in 64-bit) (int)(sum) = 17 (narrowed โ what sbuf_extendsize receives) BUGGY newsize = 32 (sbuf_extendsize returns this) (no overflow โ allocation is large enough) FIXED newsize = 32 (correct) sbuf_bcopyin path: s_size=4096, len=2147487742, SBUF_FREESPACE=4095 addlen = (int)(len - SBUF_FREESPACE) = (int)(2147483647) = 2147483647 === BUG: sbuf_bcopyin with crafted len === s_size (ssize_t) = 4096 addlen (int) = 2147483647 s_size + addlen = 2147487743 (as ssize_t, no overflow in 64-bit) (int)(sum) = -2147479553 (narrowed โ what sbuf_extendsize receives) BUGGY newsize = 16 (sbuf_extendsize returns this) *** HEAP OVERFLOW: kmalloc(16) then memcpy(4096 bytes) => 4080-byte overflow! *** FIXED newsize = ENOMEM (overflow detected, extend refused) sbuf_bcopyin path: s_size=65536, len=2147549182, addlen=2147483647 === BUG: larger s_size=65536 === s_size (ssize_t) = 65536 addlen (int) = 2147483647 s_size + addlen = 2147549183 (as ssize_t, no overflow in 64-bit) (int)(sum) = -2147418113 (narrowed โ what sbuf_extendsize receives) BUGGY newsize = 16 (sbuf_extendsize returns this) *** HEAP OVERFLOW: kmalloc(16) then memcpy(65536 bytes) => 65520-byte overflow! *** FIXED newsize = ENOMEM (overflow detected, extend refused) ============================================================= CONCLUSION: The int-truncation in sbuf_extendsize(int) is real. When s_size + addlen > INT_MAX, the narrowed argument is negative, sbuf_extendsize returns 16, and sbuf_extend's memcpy overflows the 16-byte allocation by s_size - 16 bytes. REACHABILITY: sbuf_bcopyin/sbuf_copyin/sbuf_uionew (the only callers that pass large addlen) have ZERO in-tree callers. Not reachable from unprivileged userspace. Latent code defect.