aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/uacce
diff options
context:
space:
mode:
authorZhangfei Gao <zhangfei.gao@linaro.org>2020-02-26 15:12:06 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2020-03-06 12:28:24 +1100
commitacc670dba9f57298a6afd7cdfc9a7254292bbec9 (patch)
tree410cb9948a539b6aec465e93a4af15cc63e32768 /drivers/misc/uacce
parent732e540953477083082e999ff553622c59cffd5f (diff)
downloadlinux-acc670dba9f57298a6afd7cdfc9a7254292bbec9.tar.gz
uacce: unmap remaining mmapping from user space
When uacce parent device module is removed, user app may still keep the mmaped area, which can be accessed unsafely. When rmmod, Parent device driver will call uacce_remove, which unmap all remaining mapping from user space for safety. VM_FAULT_SIGBUS is also reported to user space accordingly. Suggested-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/misc/uacce')
-rw-r--r--drivers/misc/uacce/uacce.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c
index ffced4da3c2ce..d39307f060bd6 100644
--- a/drivers/misc/uacce/uacce.c
+++ b/drivers/misc/uacce/uacce.c
@@ -224,6 +224,7 @@ 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;
return 0;
@@ -253,6 +254,14 @@ static int uacce_fops_release(struct inode *inode, struct file *filep)
return 0;
}
+static vm_fault_t uacce_vma_fault(struct vm_fault *vmf)
+{
+ if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE))
+ return VM_FAULT_SIGBUS;
+
+ return 0;
+}
+
static void uacce_vma_close(struct vm_area_struct *vma)
{
struct uacce_queue *q = vma->vm_private_data;
@@ -265,6 +274,7 @@ static void uacce_vma_close(struct vm_area_struct *vma)
}
static const struct vm_operations_struct uacce_vm_ops = {
+ .fault = uacce_vma_fault,
.close = uacce_vma_close,
};
@@ -556,6 +566,12 @@ 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);
/* ensure no open queue remains */
mutex_lock(&uacce->mm_lock);