CVE-2016-9031
An exploitable integer overflow exists in the Joyent SmartOS OS 20161110T013148Z Hyprlofs file system. The vulnerability is present in the Ioctl system call with the command HYPRLOFS_ADD_ENTRIES when dealing with 32-bit file systems. An attacker can craft an input that can cause a kernel panic and potentially be leveraged into a full privilege escalation vulnerability. This vulnerability is distinct from CVE-2016-8733.
Joyent SmartOS 20161110T013148Z
https://www.joyent.com/smartos
7.8 - CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
CWE-190: Integer Overflow or Wraparound
Joyent SmartOS is an operating system deployed by Joyent to be used as a hypervisor like solution meaning virtual machines will run on top of the system itself. SmartOS is unique in the fact that it is based on a fork of Opensolaris. This leaves many vulnerabilities in the kernel due to the fact that it is not as actively developed as other operating systems. Hyprlofs is a file system specifically designed for SmartOS which allows the creation of new virtual file systems quickly and easily. This was developed and designed to help make their product, Manta, possible.
Most of the controls for Hyprlofs go through the Ioctl calls. An Ioctl is a control function that operates on various streams in this case a file descriptor to the file system. Looking further into that code we can spot the vulnerability. The beginning of the function is shown below.
`illumos-joyent-master/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c`
static int
134 hyprlofs_ioctl(vnode_t *vp, int cmd, intptr_t data, int flag,
cred_t *cr, int *rvalp, caller_context_t *ct)
{
int len, cnt, error; [1]
...
if (secpolicy_hyprlofs_control(cr) != 0)
return (EPERM);
if (cmd == HYPRLOFS_ADD_ENTRIES || cmd == HYPRLOFS_RM_ENTRIES) { [2]
if (model == DATAMODEL_NATIVE) {
...
} else {
hyprlofs_entries32_t ebuf32;
hyprlofs_entry32_t *e32;
218 if (copyin((void *)data, &ebuf32, sizeof (ebuf32)))
return (EFAULT);
cnt = ebuf32.hle_len; [3[]
if (cnt > MAX_IOCTL_PARAMS)
return (EINVAL);
226 len = sizeof (hyprlofs_entry32_t) * cnt;
e32 = kmem_alloc(len, KM_SLEEP);
if (copyin((void *)(unsigned long)(ebuf32.hle_entries),
At [1] we see that these variables are labeled as integers. Continuing on we see that [2] is verifying which command we have chosen and if it is HYPRLOFS_ADD_ENTRIES it copies in the data directly from the user. This code path is taken if an alternative data model (for 32-bit file systems) is used. The vulnerability is present at [3], when the user supplied length, which is an unsigned integer, becomes cast to a signed integer. This allows us to bypass the check at [4] by supplying an integer that is large enough to wrap around to a negative value when cast to an int. This then passes in a large value to malloc causing failure and a NULL to be returned. Since there is no check before use at [6], the kernel will subsequently write to the NULL page, leading to a potential privilege escalation from an exploit that has mapped the NULL page in userspace.
ffffff0006b212a0 vpanic()
ffffff0006b213d0 vmem_xalloc+0x78b(ffffff020140d000, ffffffffffffffe0, 1000, 0, 0, 0, 0, 0)
ffffff0006b21440 vmem_alloc+0x135(ffffff020140d000, ffffffffffffffe0, 0)
ffffff0006b21480 kmem_alloc+0x173(ffffffffffffffe0, 0)
ffffff0006b21d50 hyprlofs_ioctl+0x18b(ffffff0215035980, 4801, fffffd7fffdffb90, 202001, ffffff021413a000, ffffff0006b21ea8, 0)
ffffff0006b21de0 fop_ioctl+0x55(ffffff0215035980, 4801, fffffd7fffdffb90, 202001, ffffff021413a000, ffffff0006b21ea8, 0)
ffffff0006b21f00 ioctl+0x9b(3, 4801, fffffd7fffdffb90)
ffffff0006b21f10 sys_syscall+0x1a2()
2016-12-01 - Vendor Disclosure
2016-12-12 - Public Release
Discovered by Tyler Bohan of Cisco Talos.