DragonFlyBSD Kernel Audit
DF-2768 / fix.diff
← back to finding ↓ download raw
DF-2768: enforce the MAXPTYS pty limit at the correct bound

devfs_clone_bitmap_get() refuses only units strictly greater than its
limit argument (sys/vfs/devfs/devfs_helper.c:224-227), so passing
MAXPTYS (== the number of entries in ptis[]) allows unit == MAXPTYS
through.  ptyclone() then executes

    if ((pti = ptis[unit]) == NULL) ...     /* tty_pty.c:186  OOB read  */
    ptis[unit] = pti;                       /* tty_pty.c:190  OOB write */

one element past the end of the 1000-entry ptis array (tty_pty.c:1292).
The OOB read consumes uninitialized heap slack as a pt_ioctl pointer
(currently NULL only because kmalloc's M_ZERO bzero happens to cover the
full 8192-byte zone chunk for an 8000-byte request), and the OOB write
stores a kernel heap pointer past the requested allocation size.  It also
creates a functional 1001st pty, bypassing the MAXPTYS guard.

Fix: pass MAXPTYS-1 (the highest valid unit number).

--- sys/kern/tty_pty.c.orig
+++ sys/kern/tty_pty.c
@@ -173,7 +173,7 @@
 	 * If this limit is reached, we don't clone and return an error
 	 * to devfs.
 	 */
-	unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(pty), MAXPTYS);
+	unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(pty), MAXPTYS - 1);

 	if (unit < 0) {
 		ap->a_dev = NULL;