Talos Vulnerability Report

TALOS-2016-0249

Joyent SmartOS Hyprlofs FS IOCTL 32-bit File System Integer Overflow Privilege Escalation Vulnerability

December 12, 2016

Report ID

CVE-2016-9031

Summary

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.

Tested Versions

Joyent SmartOS 20161110T013148Z

Product URLs

https://www.joyent.com/smartos

CVSSv3 Score

7.8 - CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-190: Integer Overflow or Wraparound

Details

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.

Crash Information

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()

Credit

Discovered by Tyler Bohan of Cisco Talos .

Timeline

2016-12-01 - Vendor Disclosure
2016-12-12 - Public Release