summaryrefslogtreecommitdiff
path: root/include/media
diff options
context:
space:
mode:
authorLin Ma <linma@zju.edu.cn>2022-08-07 17:59:52 +0300
committerMauro Carvalho Chehab <mchehab@kernel.org>2022-11-25 13:08:23 +0300
commit0fc044b2b5e2d05a1fa1fb0d7f270367a7855d79 (patch)
treebbf176c361eb5d46f8b79d923239f42363c5ba9a /include/media
parent9b7de3c2daf503f86ab0641f377402b8d7f5e485 (diff)
downloadlinux-0fc044b2b5e2d05a1fa1fb0d7f270367a7855d79.tar.xz
media: dvbdev: adopts refcnt to avoid UAF
dvb_unregister_device() is known that prone to use-after-free. That is, the cleanup from dvb_unregister_device() releases the dvb_device even if there are pointers stored in file->private_data still refer to it. This patch adds a reference counter into struct dvb_device and delays its deallocation until no pointer refers to the object. Link: https://lore.kernel.org/linux-media/20220807145952.10368-1-linma@zju.edu.cn Signed-off-by: Lin Ma <linma@zju.edu.cn> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'include/media')
-rw-r--r--include/media/dvbdev.h31
1 files changed, 17 insertions, 14 deletions
diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h
index 6ccff7c6fa6b..fad9871157e2 100644
--- a/include/media/dvbdev.h
+++ b/include/media/dvbdev.h
@@ -160,6 +160,7 @@ struct dvb_adapter {
*/
struct dvb_device {
struct list_head list_head;
+ struct kref ref;
const struct file_operations *fops;
struct dvb_adapter *adapter;
enum dvb_device_type type;
@@ -192,6 +193,20 @@ struct dvb_device {
};
/**
+ * dvb_device_get - Increase dvb_device reference
+ *
+ * @dvbdev: pointer to struct dvb_device
+ */
+struct dvb_device *dvb_device_get(struct dvb_device *dvbdev);
+
+/**
+ * dvb_device_get - Decrease dvb_device reference
+ *
+ * @dvbdev: pointer to struct dvb_device
+ */
+void dvb_device_put(struct dvb_device *dvbdev);
+
+/**
* dvb_register_adapter - Registers a new DVB adapter
*
* @adap: pointer to struct dvb_adapter
@@ -235,29 +250,17 @@ int dvb_register_device(struct dvb_adapter *adap,
/**
* dvb_remove_device - Remove a registered DVB device
*
- * This does not free memory. To do that, call dvb_free_device().
+ * This does not free memory. dvb_free_device() will do that when
+ * reference counter is empty
*
* @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);