XADV-2013005 FreeBSD 10 <= nand Driver IOCTL Kernel Memory Leak Bug 1. Overview The nand driver in freebsd <= 10 has a vulnerability to leak arbitrary kernel memory to the userspace. It's occured at nand_ioctl() kernel function and because no proper initialize the allocated kernel memory. * Vulnerable Source Code: - http://fxr.watson.org/fxr/source/dev/nand/nand_geom.c?v=FREEBSD10 * Credit: - x90c (site: http://www.x90c.org) * References: [1] http://www.unix.com/man-page/freebsd/9/malloc/ [2] http://fxr.watson.org/fxr/source/dev/ath/if_ath.c?v=FREEBSD10#L5881 [3] https://wiki.freebsd.org/BSDDay_2010?action=AttachFile&do=get&target=bsdday2010-flash_subsystem.pdf 2. Details The kmem leak bug at nand_ioctl() in /dev/nand/nand_geom.c. [/dev/nand/nand_geom.c?v=FREEBSD10#L191] ---- 191 static int 192 nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag, 193 struct thread *td) 194 { 195 struct nand_chip *chip; 196 struct nand_oob_rw *oob_rw = NULL; 197 struct nand_raw_rw *raw_rw = NULL; 198 device_t nandbus; 199 uint8_t *buf = NULL; 200 int ret = 0; 201 uint8_t status; 202 203 chip = (struct nand_chip *)ndisk->d_drv1; 204 nandbus = device_get_parent(chip->dev); 205 // XXX NAND_IO_RAW_READ or NAND_IO_RAW_PROG ioctl cmd. 206 if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) { 207 raw_rw = (struct nand_raw_rw *)data; // XXX raw_rw = data(arg) /* * XXX malloc'd buf = raw_rw->len. * exp cond1) user-supplied raw_rw->len can be success allocated. * and return a large chunk uninitialized causing kmem leak refer to [1]. * the fix needed M_ZERO flag to zero the allocated kmem. */ 208 buf = malloc(raw_rw->len, M_NAND, M_WAITOK); 209 } 210 switch (cmd) { ... 242 case NAND_IO_RAW_READ: 243 ret = nand_read_pages_raw(chip, raw_rw->off, buf, 244 raw_rw->len); /* * XXX Uninitialized kmem(buf) leaks to raw_rw->data(userspace). * If subsequence ioctl ... can be leak all of free'd kmem in * malloc area. */ 245 copyout(buf, raw_rw->data, raw_rw->len); 246 break; 247 ... 260 return (ret); 261 } ---- 3. Patch code [freebsd_nand_kmem_leak.patch] ---- - buf = malloc(raw_rw->len, M_NAND, M_WAITOK); + buf = malloc(raw_rw->len, M_NAND, M_WAITOK | M_ZERO); /* to zero the allocated kmem */ ---- 4. Vendor Status - 2013/11/13 I discovered the memory leak bug and reported to the secteam@freebsd.org. - 2013/11/14 The vendor response with the coordination. (will be freebsd's advisory) - 2013/11/16 Cve-id request to the cve-assign@mitre.org. - 2013/11/16 The original advisory released on full-disclosure, bugtraq. EOF