Re: KASAN: use-after-free Write in hiddev_disconnect

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm trying to take a stab at diagnosing these bugs.  (But I'm seldom
smart enough to actually fix anything).  These hiddev_disconnect() bugs
are a race condition:

devel/drivers/hid/usbhid/hiddev.c
   924  void hiddev_disconnect(struct hid_device *hid)
   925  {
   926          struct hiddev *hiddev = hid->hiddev;
   927          struct usbhid_device *usbhid = hid->driver_data;
   928  
   929          usb_deregister_dev(usbhid->intf, &hiddev_class);
   930  
   931          mutex_lock(&hiddev->existancelock);
   932          hiddev->exist = 0;
                ^^^^^^^^^^^^^^^^^^
We set "exist = 0;"

   933  
   934          if (hiddev->open) {
   935                  mutex_unlock(&hiddev->existancelock);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Then we drop the lock.

   936                  hid_hw_close(hiddev->hid);
   937                  wake_up_interruptible(&hiddev->wait);
                                               ^^^^^^
The other thread frees hiddev and it crashes here.

   938          } else {
   939                  mutex_unlock(&hiddev->existancelock);
   940                  kfree(hiddev);
   941          }
   942  }

The other thread is doing:

drivers/hid/usbhid/hiddev.c
   216  static int hiddev_release(struct inode * inode, struct file * file)
   217  {
   218          struct hiddev_list *list = file->private_data;
   219          unsigned long flags;
   220  
   221          spin_lock_irqsave(&list->hiddev->list_lock, flags);
   222          list_del(&list->node);
   223          spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
   224  
   225          mutex_lock(&list->hiddev->existancelock);
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Takes the lock.

   226          if (!--list->hiddev->open) {
                     ^^^^^^^^^^^^^^^^^^^^
Decrements open.

   227                  if (list->hiddev->exist) {
                            ^^^^^^^^^^^^^^^^^^^
This is false.

   228                          hid_hw_close(list->hiddev->hid);
   229                          hid_hw_power(list->hiddev->hid, PM_HINT_NORMAL);
   230                  } else {
   231                          mutex_unlock(&list->hiddev->existancelock);
   232                          kfree(list->hiddev);
                                      ^^^^^^^^^^^^
Freed here.

   233                          vfree(list);
   234                          return 0;
   235                  }
   236          }
   237  
   238          mutex_unlock(&list->hiddev->existancelock);
   239          vfree(list);
   240  
   241          return 0;
   242  }

I'm not sure what the fix should be though.

regards,
dan carpenter




[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux