<<< Date Index >>>     <<< Thread Index >>>

Re: Linux Kernel i2c Integer Overflow Vulnerability



> --- vuln code ---
> ssize_t i2cproc_bus_read(struct file * file, char *
> buf,size_t count, 
>                           loff_t *ppos)
>  {
>          struct inode * inode =
> file->f_dentry->d_inode;
>          char *kbuf;
>          struct i2c_client *client;
>          int i,j,k,order_nr,len=0;
>          size_t len_total;
>          int order[I2C_CLIENT_MAX];
>  
>          if (count > 4000)
>                  return -EINVAL; 
>          len_total = file->f_pos + count;
>          /* Too bad if this gets longer (unlikely) */
>          if (len_total > 4000)
>                  len_total = 4000;
>          for (i = 0; i < I2C_ADAP_MAX; i++)
>                  if (adapters[i]->inode ==
> inode->i_ino) {
>                  /* We need a bit of slack in the
> kernel buffer; this makes the
>                     sprintf safe. */
>                          if (! (kbuf = kmalloc(count +
> 80,GFP_KERNEL)))
>                                  return -ENOMEM;
> 
> [...]
> 
> --- end snippet ---
> 
> Although a quick check is made to ensure that the
> user-supplied variable 'count' does not exceed 4000,
> sanity checks do not occur to check for negative
> integers in 'count'.  Since negative integers simply
> become _very_ large integers when represented as
> unsigned, a negative count argument to kmalloc() would
> cause unexpected behavior:
> 

On i386:
typedef __kernel_size_t         size_t;
typedef unsigned int    __kernel_size_t;

asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count);
                                                        ^^^^^^^

You can't pass negative values, all archs have unsigned definitions of
size_t. Therefor "if (count > 4000)" is an ok range check.


> ---
>  if (! (kbuf = kmalloc(count + 80,GFP_KERNEL)))
> ---
> 
> For example, if '-1' was passed to the routine as the
> 'count' argument, the above kmalloc() call would be
> equivalent to below:
> 
> ---
>  if (! (kbuf = kmalloc(0xffffffff + 80,GFP_KERNEL)))
> ---
> 
> This would cause an integer overflow during the
> kmalloc() call when 80 is added to count, resulting in
> a very small amount of memory being allocated.
> 
> As in the comment just above the vulnerable kmalloc()
> call (/* We need a bit of slack in the kernel buffer;
> this makes the sprintf safe. */), the purpose of
> incrementing the 'count' argument by 80 is to stop the
> chance of a buffer overflow, but by supplying a
> suitable negative integer as 'count' (i.e -1), this
> allows an integer overflow, causing the kmalloc()
> argument to wrap back round to a small/negative value.
> 
> In the sprintf() calls following the kmalloc() call,
> there is quite a possibility of overflowing the bounds
> of the newly allocated very small chunk of memory. 
> This might result in kernel panic, corruption of
> kernel memory, or maybe even elevation of privileges
> (*very* unlikely).
> 
> i2cproc_bus_read() is implemented as a read() hook in
> the driver, as below:
> 
> ---
> static struct file_operations i2cproc_operations = {
>          read:           i2cproc_bus_read,
>  };
> ---
> 
> This might allow unprivileged users to exploit the
> issue.
> 
> Please take note that this potential security hole
> only affects those using the i2c driver -- if this
> driver (it can be installed as either a module or
> built into the kernel) is not installed on your
> system, you're not vulnerable.  The issue is present
> in all 2.4 kernels, including the latest release.
> 
> 
> 
> Solution
> #########
> 
> The following sanity check can be added to the
> beginning of the i2cproc_bus_read() in the i2c-core.c
> file:
> 
> ---
> if(count < 0)
>         return -EINVAL;
> ---
> 
> Then rebuild the kernel, and the issue should be
> resolved.
> 
> A possible workaround would be to perhaps disable the
> module or remove the driver if it's not needed on your
> system.
> 
> 
> 
> Disclaimer
> ###########
> 
> The information contained within this advisory was
> believed to be accurate at the time of it's
> publishing.  However, it might be inaccurate at times,
> so don't consider any information contained within
> definitely correct.
> 
> Direct flames to /dev/null.  Don't bothering wasting
> your time and mine with any crap about any disclosure
> policies I may or may not have followed -- I'm not
> interested, so I'll just ignore you if you don't
> phrase things nicely.
> 
> 
> 
> Thank you for your time.
> Shaun.
> 
> 
>       
>       
>               
> ___________________________________________________________ALL-NEW Yahoo! 
> Messenger - sooooo many all-new ways to express yourself 
> http://uk.messenger.yahoo.com