OSDN Git Service

uacce: use q->mapping to replace inode->i_mapping
authorZhangfei Gao <zhangfei.gao@linaro.org>
Thu, 11 May 2023 09:59:20 +0000 (17:59 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 May 2023 18:00:26 +0000 (19:00 +0100)
The inode can be different in a container, for example, a docker and host
both open the same uacce parent device, which uses the same uacce struct
but different inode, so uacce->inode is not enough.

What's worse, when docker stops, the inode will be destroyed as well,
causing use-after-free in uacce_remove.

So use q->mapping to replace uacce->inode->i_mapping.

Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Link: https://lore.kernel.org/r/20230511095921.9331-2-zhangfei.gao@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/uacce/uacce.c
include/linux/uacce.h

index 346bd7c..338b59e 100644 (file)
@@ -166,8 +166,8 @@ static int uacce_fops_open(struct inode *inode, struct file *filep)
 
        init_waitqueue_head(&q->wait);
        filep->private_data = q;
-       uacce->inode = inode;
        q->state = UACCE_Q_INIT;
+       q->mapping = filep->f_mapping;
        mutex_init(&q->mutex);
        list_add(&q->list, &uacce->queues);
        mutex_unlock(&uacce->mutex);
@@ -574,12 +574,6 @@ void uacce_remove(struct uacce_device *uacce)
 
        if (!uacce)
                return;
-       /*
-        * unmap remaining mapping from user space, preventing user still
-        * access the mmaped area while parent device is already removed
-        */
-       if (uacce->inode)
-               unmap_mapping_range(uacce->inode->i_mapping, 0, 0, 1);
 
        /*
         * uacce_fops_open() may be running concurrently, even after we remove
@@ -597,6 +591,12 @@ void uacce_remove(struct uacce_device *uacce)
                uacce_put_queue(q);
                mutex_unlock(&q->mutex);
                uacce_unbind_queue(q);
+
+               /*
+                * unmap remaining mapping from user space, preventing user still
+                * access the mmaped area while parent device is already removed
+                */
+               unmap_mapping_range(q->mapping, 0, 0, 1);
        }
 
        /* disable sva now since no opened queues */
index 0a81c3d..e290c02 100644 (file)
@@ -86,6 +86,7 @@ enum uacce_q_state {
  * @state: queue state machine
  * @pasid: pasid associated to the mm
  * @handle: iommu_sva handle returned by iommu_sva_bind_device()
+ * @mapping: user space mapping of the queue
  */
 struct uacce_queue {
        struct uacce_device *uacce;
@@ -97,6 +98,7 @@ struct uacce_queue {
        enum uacce_q_state state;
        u32 pasid;
        struct iommu_sva *handle;
+       struct address_space *mapping;
 };
 
 /**
@@ -114,7 +116,6 @@ struct uacce_queue {
  * @mutex: protects uacce operation
  * @priv: private pointer of the uacce
  * @queues: list of queues
- * @inode: core vfs
  */
 struct uacce_device {
        const char *algs;
@@ -130,7 +131,6 @@ struct uacce_device {
        struct mutex mutex;
        void *priv;
        struct list_head queues;
-       struct inode *inode;
 };
 
 #if IS_ENABLED(CONFIG_UACCE)