catalinv-ncc opened a new issue, #19170:
URL: https://github.com/apache/nuttx/issues/19170

   ### Description / Steps to reproduce the issue
   
   drivers/eeprom: Integer Overflow in I2C EEPROM `ee24xx_seek()` Kernel 
Operation
   
   ## Impact
   
   A compromised user process may use:
   
   * an out-of-bound read to exfiltrate kernel memory, or
   * an out-of-bound write to modify the kernel memory.
   
   At a minimum, accessing out-of-bounds memory cause a device crash.
   
   ## Description
   
   When accessing the I2C EEPROM storage, the user applications will use code 
such as 
   
   ```c
   fd = open("/dev/eeprom");
   num_bytes_read = read(fd, buffer, len);
   ```
   
   These calls will use the following kernel driver code:
   
   ```c
   static const struct file_operations g_ee24xx_fops =
   {
     ee24xx_open,  /* open */
     ee24xx_close, /* close */
     ee24xx_read,  /* read */
     ee24xx_write, /* write */
     ee24xx_seek,  /* seek */
     ee24xx_ioctl, /* ioctl */
   };
   
   int ee24xx_initialize(FAR struct i2c_master_s *bus, uint8_t devaddr,
                         FAR char *devname, int devtype, int readonly)
   {
   ...
     return register_driver_with_size(devname, &g_ee24xx_fops, 0666, eedev,
                                      eedev->size);
   }
   ```
   
   The function seek which allows the user to move the cursor to a particular 
offset in order to read and write from EEPROM storage does not validate the 
offset is valid. Later, this can cause an out-of-bounds reads or writes. Note 
that `newpos` may store a large value, larger than the size of the EEPROM.
   
   ```c
   static off_t ee24xx_seek(FAR struct file *filep, off_t offset, int whence)
   {
   ...
     ret = nxmutex_lock(&eedev->lock);
     if (ret < 0)
       {
         return ret;
       }
   
     switch (whence)
       {
       case SEEK_CUR:
         newpos = filep->f_pos + offset;
         break;
       case SEEK_SET:
         newpos = offset;
         break;
       case SEEK_END:
         newpos = eedev->size + offset;
         break;
       default:
         /* Return EINVAL if the whence argument is invalid */
         nxmutex_unlock(&eedev->lock);
         return -EINVAL;
       }
   
     if (newpos >= 0)
       {
         filep->f_pos = newpos;
         ret = newpos;
         finfo("SEEK newpos %" PRIdOFF "\n", newpos);
       }
     else
       {
         ret = -EINVAL;
       }
   ...
   }
   ```
   
   When the I2C EEPROM kernel driver is initialized, the size (in bytes) of the 
storage device is stored in `eedev->size`.
   
   Later in `ee24xx_read()` and `ee24xx_write()` can be tricked and bypass the 
checks below. For the read operation, the cursor can be set to a very large 
value, and `filep->f_pos + len` can overflow, resulting in a small value, less 
than `eedev->size`. For the write operation, the cursor needs to be in the 
normal range, i.e. `0` to `eedev->size` due to the first check, but if the 
value of `len` is very large `len + filep->f_pos` will overflow and will bypass 
the second check.
   
   ```c
   static ssize_t ee24xx_read(FAR struct file *filep, FAR char *buffer, size_t 
len)
   {
   ...
     /* trim len if read would go beyond end of device */
     if ((filep->f_pos + len) > eedev->size)
       {
         len = eedev->size - filep->f_pos;
       }
   ...
   }
   
   static ssize_t ee24xx_write(FAR struct file *filep, FAR const char *buffer, 
size_t len)
   {
   ...
     if (filep->f_pos >= eedev->size)
       {
         return -EFBIG;
       }
   ...
     /* Clamp len to avoid crossing the end of the memory */
     if ((len + filep->f_pos) > eedev->size)
       {
         len = eedev->size - filep->f_pos;
         finfo("Len clamped to %zu\n", len);
       }
   ```
   
   ## Recommendation
   
   Check that `filep->f_pos + len` operations performed by the read and write 
functions do not overflow, otherwise return an error code.
   
   ### On which OS does this issue occur?
   
   [OS: Linux]
   
   ### What is the version of your OS?
   
   Ubuntu 24.04
   
   ### NuttX Version
   
   master
   
   ### Issue Architecture
   
   [Arch: all]
   
   ### Issue Area
   
   [Area: Drivers]
   
   ### Host information
   
   _No response_
   
   ### Verification
   
   - [x] I have verified before submitting the report.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to