SecurityTracker.com
    Home    |    View Topics    |    Search    |    Contact Us    |   

SecurityTracker
Archives


 


Category:   OS (Linux)  >   Linux Kernel Vendors:   kernel.org
Linux Kernel SBus PROM Driver Integer Overflows Let Local Users Crash the System
SecurityTracker Alert ID:  1010617
SecurityTracker URL:  http://securitytracker.com/id/1010617
CVE Reference:   GENERIC-MAP-NOMATCH   (Links to External Site)
Date:  Jun 30 2004
Impact:   Denial of service via local system


Description:   Several integer overflow vulnerabilities were reported in the Linux kernel in the SBus PROM driver. A local user can cause denial of service conditions.

Sean reported that a local user can supply specially crafted values to overflow some integer variables, causing buffers to be allocated that are too small to copy the amount of user-supplied data.

The report indicated that the source of the driver is generally located at:

/usr/src/linux/drivers/sbus/char/openprom.c

The flaws reportedly reside in the copyin() and copyin_string() functions.

The report states that it may be possible to execute arbitrary code, but that was not confirmed.

The vendor was reportedly notified.

Impact:   A local user can cause the system to crash.
Solution:   No solution was available at the time of this entry.
Cause:   Boundary error

Message History:   None.


 Source Message Contents

Subject:  linux kernel Sbus PROM driver multiple integer overflows


Sbus PROM driver multiple integer overflows
-------------------------------------------

Description:

    This character device driver allows user programs to access the PROM
    device tree. It is compatible with the SunOS /dev/openprom driver and the
    NetBSD /dev/openprom driver. The SunOS eeprom utility works without any
    modifications.

Source:
    
    This driver is distributed by default in all of the distros that I have.
    It's source can be found:
        /usr/src/linux/drivers/sbus/char/openprom.c

Impact:
    
    Local DOS, possible code execution depending on location of the overflowed
    buffer in the slab.

Bug:

    There exist multiple integer overflows in routines that handle copying in
    user supplied data.  In both routines, user supplied parameters are used
    to allocate buffers after being added to another number.  Passing certain
    values will result in integer overflows and small buffers being allocated.
    Then large amounts of user data are copied into these buffers.  Both of
    the functions in which the overflows occur are 'utility' functions called
    from multiple other functions.  An ioctl() call is the simplest way to
    access them.


Detail:

    The copyin() and the copyin_string() function are both vulnerable:


/* Copy in a whole string from userspace into kernelspace. */
static int copyin_string(char *user, size_t len, char **ptr)
{
        char *tmp;

    /* ME: it's not signed; if( len + 1 < len ) .. */
1]      if (len < 0 || len + 1 < 0)
                return -EINVAL;

2]      tmp = kmalloc(len + 1, GFP_KERNEL);
        if (!tmp)
                return -ENOMEM;

3]      if(copy_from_user(tmp, user, len)) {
                kfree(tmp);
                return -EFAULT;
        }
..... snip  .....

    In this function it appears they forgot that size_t is not signed.  The
    checks made at 1] will never be true, and by passing in ~0 for the len
    variable an integer overflow occurs at 2].  Then at 3] user supplied data
    is copied int this buffer.  In various ioctl() calls for both the bsd and
    sun versions the user has full control over the user and len variables.
    

static int copyin(struct openpromio *info, struct openpromio **opp_p)
{
        int bufsize;

        if (!info || !opp_p)
                return -EFAULT;

1]      if (get_user(bufsize, &info->oprom_size))
                return -EFAULT;

        if (bufsize == 0)
                return -EINVAL;

        /* If the bufsize is too large, just limit it.
         * Fix from Jason Rappleye.
 	 * ME: apparently not fixed enough
         */
2]      if (bufsize > OPROMMAXPARAM)
                bufsize = OPROMMAXPARAM;

3]      if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
                return -ENOMEM;
        memset(*opp_p, 0, sizeof(int) + bufsize + 1);

4]      if (copy_from_user(&(*opp_p)->oprom_array,
                           &info->oprom_array, bufsize)) {
                kfree(*opp_p);
                return -EFAULT;
        }
        return bufsize;
}

    The bufsize integer variable obtained from the user at 1] is checked for
    being to large at 2], but it is not checked for being negative.  we then 
    have an overflow occuring at 3] when the buffer is allocated.  Then at 4] 
    this buffer is used to hold user data, resulting in memory being overwritten.

Vendor Status:
	
    The driver authors from the source listing were contacted and didn't reply.

-- 
-sean

 
 


Go to the Top of This SecurityTracker Archive Page





Home   |    View Topics   |    Search   |    Contact Us

This web site uses cookies for web analytics. Learn More

Copyright 2019, SecurityGlobal.net LLC