Bug 475733 (CVE-2008-5702) - CVE-2008-5702 kernel: watchdog: ib700wdt.c - buffer_underflow bug
Summary: CVE-2008-5702 kernel: watchdog: ib700wdt.c - buffer_underflow bug
Keywords:
Status: CLOSED ERRATA
Alias: CVE-2008-5702
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 475735 475736 475737 475738 475739
Blocks:
TreeView+ depends on / blocked
 
Reported: 2008-12-10 07:27 UTC by Eugene Teo (Security Response)
Modified: 2019-09-29 12:28 UTC (History)
4 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-12-24 03:52:28 UTC
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2009:0014 0 normal SHIPPED_LIVE Important: kernel security and bug fix update 2009-01-14 18:05:34 UTC

Description Eugene Teo (Security Response) 2008-12-10 07:27:46 UTC
From Zvonimir Rakamaric:
Steps to a possible buffer_underflow bug in ib700wdt.c, function ibwdt_ioctl:

1. new margin is loaded using get_user(new_margin, p) in case WDIOC_SETTIMEOUT in the function ibwdt_ioctl. Important: assume that new_margin == 30
2. ibwdt_set_heartbeat(new_margin) is called
3. the check "if ((t < 0) || (t > 30))" in ibwdt_set_heartbeat is not going to fail because t == 30 (t is new_margin)
4. in the loop, the check wd_times[i] > t is never going to be true because none of the wd_times are greater than the value of t (i.e. 30)
5. we are exiting the loop with i == -1 and therefore setting wd_margin to -1 in the line wd_margin = i;
6. we are returning from ibwdt_set_heartbeat and wd_margin is -1
7. we fall through to case WDIOC_GETTIMEOUT
8. we access the wd_times array with wd_margin == -1 on line "return put_user(wd_times[wd_margin], p);"

[...]
Furthermore, here are the pieces of code which are causing this
buffer-underflow bug in ib700wdt.c:

static int wd_times[] = {
        30,     /* 0x0 */
        28,     /* 0x1 */
        26,     /* 0x2 */
        24,     /* 0x3 */
        22,     /* 0x4 */
        20,     /* 0x5 */
        18,     /* 0x6 */
        16,     /* 0x7 */
        14,     /* 0x8 */
        12,     /* 0x9 */
        10,     /* 0xA */
        8,      /* 0xB */
        6,      /* 0xC */
        4,      /* 0xD */
        2,      /* 0xE */
        0,      /* 0xF */
};

function ibwdt_ioctl:
.....
  case WDIOC_SETTIMEOUT:
    if (get_user(new_margin, p))
      return -EFAULT;
    if (ibwdt_set_heartbeat(new_margin))
      return -EINVAL;
    ibwdt_ping();
    /* Fall */

  case WDIOC_GETTIMEOUT:
    return put_user(wd_times[wd_margin], p);
.....

function ibwdt_set_heartbeat:
static int
ibwdt_set_heartbeat(int t)
{
        int i;

        if ((t < 0) || (t > 30))
                return -EINVAL;

        for (i = 0x0F; i > -1; i--)
                if (wd_times[i] > t)
                        break;
        wd_margin = i;
        return 0;
}

Comment 3 Eugene Teo (Security Response) 2008-12-10 07:34:54 UTC
Reference: http://bugzilla.kernel.org/show_bug.cgi?id=11399

Comment 4 Eugene Teo (Security Response) 2008-12-10 07:35:39 UTC
Upstream commit:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7c2500f

Comment 7 Vincent Danen 2010-12-24 03:52:28 UTC
This was addressed via:

Red Hat Enterprise Linux version 4 (RHSA-2009:0014)


Note You need to log in before you can comment on or make changes to this bug.