diff options
author | Zhangfei Gao <zhangfei.gao@linaro.org> | 2023-05-11 12:59:20 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-05-31 21:00:26 +0300 |
commit | df1b056d489d98c7c45fa89627102dd34b44496f (patch) | |
tree | bf3562a5bff1da63e8e5c9b3479c47cc0bef37b3 | |
parent | 24ee010bdabb15c601ab6ce2007ad32f4ef4a880 (diff) | |
download | linux-df1b056d489d98c7c45fa89627102dd34b44496f.tar.xz |
uacce: use q->mapping to replace inode->i_mapping
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>
-rw-r--r-- | drivers/misc/uacce/uacce.c | 14 | ||||
-rw-r--r-- | include/linux/uacce.h | 4 |
2 files changed, 9 insertions, 9 deletions
diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c index 346bd7cf2e94..338b59ef5493 100644 --- a/drivers/misc/uacce/uacce.c +++ b/drivers/misc/uacce/uacce.c @@ -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 */ diff --git a/include/linux/uacce.h b/include/linux/uacce.h index 0a81c3dfd26c..e290c0269944 100644 --- a/include/linux/uacce.h +++ b/include/linux/uacce.h @@ -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) |