xorl %eax, %eax

Linux kernel w1_therm Integer Overflow

with one comment

This is another bug found on 2.6.28.6’s changelog. It was reported on LKML on 10 February 2009 by Evgeniy Polyakov. Previous kernel releases might be vulnerable. I can ensure that 2.6.28.5 is vulnerable to this bug. This bug can be found under drivers/w1/slaves/w1_therm.c where the temperature module for 1-wire Dallas network protocol is located. There is an inline function responsible for converting the requested value (temperature) to millidegrees of Centigrade scale. Here it is:

116 static inline int w1_DS18B20_convert_temp(u8 rom[9])
117 {
118        s16 t = (rom[1] << 8) | rom[0];
119        t = t*1000/16;
120        return t;
121 }

It gets an unsigned character array and returns a signed integer. But the buggy code is at line 118 where it retrieves the temperature and stores it in an s16 (aka signed short) variable. Now if the temperature exceeds sizeof(short)/2 which is 32767 it will wrap around zero and overflow. So if the temperature can be 32767 millidegrees Centigrade then the above function will return -32768. According to Ian Dall these temperatures are within the range of devices’ sensors which is from -55 up to +125. To fix this vulnerability they applied the following patch:

 {
-    s16 t = (rom[1] << 8) | rom[0];
+    int t = ((s16)rom[1] << 8) | rom[0];
     t = t*1000/16;

Now t is stored in a 32bit signed integer and thus allowing values up to 2147483647 before it’ll overflow.

Written by xorl

February 19, 2009 at 15:23

Posted in bugs, linux

One Response

Subscribe to comments with RSS.

  1. This seems to work find above freezing, but below freezing returns incorrect values.

    Joel Goldwein

    December 20, 2009 at 01:26


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