From: Dongliang Mu <mudongliangabcd@xxxxxxxxx> [ Upstream commit c08eadca1bdfa099e20a32f8fa4b52b2f672236d ] The commit 47677e51e2a4("[media] em28xx: Only deallocate struct em28xx after finishing all extensions") adds kref_get to many init functions (e.g., em28xx_audio_init). However, kref_init is called too late in em28xx_usb_probe, since em28xx_init_dev before will invoke those init functions and call kref_get function. Then refcount bug occurs in my local syzkaller instance. Fix it by moving kref_init before em28xx_init_dev. This issue occurs not only in dev but also dev->dev_next. Fixes: 47677e51e2a4 ("[media] em28xx: Only deallocate struct em28xx after finishing all extensions") Reported-by: syzkaller <syzkaller@xxxxxxxxxxxxxxxx> Signed-off-by: Dongliang Mu <mudongliangabcd@xxxxxxxxx> Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> --- drivers/media/usb/em28xx/em28xx-cards.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index b451ce3cb169..f3b56c065ee1 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3936,6 +3936,8 @@ static int em28xx_usb_probe(struct usb_interface *intf, goto err_free; } + kref_init(&dev->ref); + dev->devno = nr; dev->model = id->driver_info; dev->alt = -1; @@ -4036,6 +4038,8 @@ static int em28xx_usb_probe(struct usb_interface *intf, } if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) { + kref_init(&dev->dev_next->ref); + dev->dev_next->ts = SECONDARY_TS; dev->dev_next->alt = -1; dev->dev_next->is_audio_only = has_vendor_audio && @@ -4090,12 +4094,8 @@ static int em28xx_usb_probe(struct usb_interface *intf, em28xx_write_reg(dev, 0x0b, 0x82); mdelay(100); } - - kref_init(&dev->dev_next->ref); } - kref_init(&dev->ref); - request_modules(dev); /* -- 2.34.1