dvb_frontend_open() calls dvb_generic_release() in its error path after
dvb_generic_open() succeeds. dvb_generic_release() drops the device
reference via dvb_device_put(), and then dvb_device_open() drops it again
in its error handling, causing a use-after-free and refcount underflow.
Fix this by incrementing the refcount before dvb_generic_release() in the
error path, so that the put inside dvb_generic_release() is balanced and
dvb_device_open() remains the sole effective put on open failure.
Reported-by: syzbot+40339ea82afa8184ad5d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=40339ea82afa8184ad5d
Cc: stable@vger.kernel.org
Fixes: 0fc044b2b5e2 ("media: dvbdev: adopts refcnt to avoid UAF")
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
---
v3:
- Simplify fix: increment refcount before dvb_generic_release() instead
of introducing __dvb_generic_release()
v2:
- Fix Fixes tag commit title
- Add Closes: link after Reported-by
- Cc stable@vger.kernel.org
drivers/media/dvb-core/dvb_frontend.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index d082b6c57c76..608525d08277 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2887,6 +2887,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
mutex_unlock(&fe->dvb->mdev_lock);
err2:
#endif
+ dvb_device_get(dvbdev);
dvb_generic_release(inode, file);
err1:
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
--
2.43.0