[media] dvbdev: split dvb_unregister_device()
authorMax Kellermann <max.kellermann@gmail.com>
Tue, 9 Aug 2016 21:32:11 +0000 (18:32 -0300)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Fri, 18 Nov 2016 17:02:39 +0000 (15:02 -0200)
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 <max.kellermann@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/dvb-core/dvbdev.c
drivers/media/dvb-core/dvbdev.h

index 0694d1d53c677ac45ce75be3558c960acb148587..38c844667789361d1385f6609b30fedade294bcd 100644 (file)
@@ -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);
 
 
index 4aff7bd3dea89415cc98074116e94b8f07f38198..576bbd4445b5fa6994af6bfd923ef1853b079908 100644 (file)
@@ -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);