Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: gadget: f_hid: don't call cdev_init while cdev in use

When calling unbind, then bind again, cdev_init reinitialized the cdev,
even though there may still be references to it. That's the case when
the /dev/hidg* device is still opened. This obviously unsafe behavior
like oopes.

This fixes this by using cdev_alloc to put the cdev on the heap. That
way, we can simply allocate a new one in hidg_bind.

Closes: https://lore.kernel.org/linux-usb/CAN9vWDKZn0Ts5JyV2_xcAmbnBEi0znMLg_USMFrShRryXrgWGQ@mail.gmail.com/T/#m2cb0dba3633b67b2a679c98499508267d1508881
Cc: stable <stable@kernel.org>
Signed-off-by: Michael Zimmermann <sigmaepsilon92@gmail.com>
Link: https://patch.msgid.link/20260327192209.59945-1-sigmaepsilon92@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Michael Zimmermann and committed by
Greg Kroah-Hartman
81ebd43c 0c893564

+10 -5
+10 -5
drivers/usb/gadget/function/f_hid.c
··· 106 106 struct list_head report_list; 107 107 108 108 struct device dev; 109 - struct cdev cdev; 109 + struct cdev *cdev; 110 110 struct usb_function func; 111 111 112 112 struct usb_ep *in_ep; ··· 749 749 750 750 static int f_hidg_open(struct inode *inode, struct file *fd) 751 751 { 752 + struct kobject *parent = inode->i_cdev->kobj.parent; 752 753 struct f_hidg *hidg = 753 - container_of(inode->i_cdev, struct f_hidg, cdev); 754 + container_of(parent, struct f_hidg, dev.kobj); 754 755 755 756 fd->private_data = hidg; 756 757 ··· 1286 1285 } 1287 1286 1288 1287 /* create char device */ 1289 - cdev_init(&hidg->cdev, &f_hidg_fops); 1290 - status = cdev_device_add(&hidg->cdev, &hidg->dev); 1288 + hidg->cdev = cdev_alloc(); 1289 + if (!hidg->cdev) 1290 + goto fail_free_all; 1291 + hidg->cdev->ops = &f_hidg_fops; 1292 + 1293 + status = cdev_device_add(hidg->cdev, &hidg->dev); 1291 1294 if (status) 1292 1295 goto fail_free_all; 1293 1296 ··· 1593 1588 { 1594 1589 struct f_hidg *hidg = func_to_hidg(f); 1595 1590 1596 - cdev_device_del(&hidg->cdev, &hidg->dev); 1591 + cdev_device_del(hidg->cdev, &hidg->dev); 1597 1592 destroy_workqueue(hidg->workqueue); 1598 1593 usb_free_all_descriptors(f); 1599 1594 }