From 1f4ed6cd58f36574237926f35bdec50116669909 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 9 Aug 2016 18:32:11 -0300 Subject: [PATCH] [media] dvbdev: split dvb_unregister_device() dvb_unregister_device() has a major problem: it combines unregistering with memory disposal. Sometimes, it is necessary to unregister a device, but no memory can be freed yet, because a process still has a (stale) file handle. Therefore, we need to split dvb_unregister_device(). This will allow sanitizing a few callers. With my new design, dvb_unregister_device() appears misnamed, but to reduce patch noise, I'm not renaming it just yet. Signed-off-by: Max Kellermann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 19 ++++++++++++++++++- drivers/media/dvb-core/dvbdev.h | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 0694d1d53c67..38c844667789 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -528,7 +528,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, EXPORT_SYMBOL(dvb_register_device); -void dvb_unregister_device(struct dvb_device *dvbdev) +void dvb_remove_device(struct dvb_device *dvbdev) { if (!dvbdev) return; @@ -542,9 +542,26 @@ void dvb_unregister_device(struct dvb_device *dvbdev) device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); list_del (&dvbdev->list_head); +} +EXPORT_SYMBOL(dvb_remove_device); + + +void dvb_free_device(struct dvb_device *dvbdev) +{ + if (!dvbdev) + return; + kfree (dvbdev->fops); kfree (dvbdev); } +EXPORT_SYMBOL(dvb_free_device); + + +void dvb_unregister_device(struct dvb_device *dvbdev) +{ + dvb_remove_device(dvbdev); + dvb_free_device(dvbdev); +} EXPORT_SYMBOL(dvb_unregister_device); diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h index 4aff7bd3dea8..576bbd4445b5 100644 --- a/drivers/media/dvb-core/dvbdev.h +++ b/drivers/media/dvb-core/dvbdev.h @@ -211,9 +211,32 @@ int dvb_register_device(struct dvb_adapter *adap, int type, int demux_sink_pads); +/** + * dvb_remove_device - Remove a registered DVB device + * + * This does not free memory. To do that, call dvb_free_device(). + * + * @dvbdev: pointer to struct dvb_device + */ +void dvb_remove_device(struct dvb_device *dvbdev); + +/** + * dvb_free_device - Free memory occupied by a DVB device. + * + * Call dvb_unregister_device() before calling this function. + * + * @dvbdev: pointer to struct dvb_device + */ +void dvb_free_device(struct dvb_device *dvbdev); + /** * dvb_unregister_device - Unregisters a DVB device * + * This is a combination of dvb_remove_device() and dvb_free_device(). + * Using this function is usually a mistake, and is often an indicator + * for a use-after-free bug (when a userspace process keeps a file + * handle to a detached device). + * * @dvbdev: pointer to struct dvb_device */ void dvb_unregister_device(struct dvb_device *dvbdev);