โฌข DragonFlyBSD Kernel Audit
DF-2552 / run.log
โ† back to finding โ†“ download raw
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.