|
@@ -1361,6 +1361,19 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
|
|
ret = -EINVAL;
|
|
|
if (!vma_can_userfault(cur))
|
|
|
goto out_unlock;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * UFFDIO_COPY will fill file holes even without
|
|
|
+ * PROT_WRITE. This check enforces that if this is a
|
|
|
+ * MAP_SHARED, the process has write permission to the backing
|
|
|
+ * file. If VM_MAYWRITE is set it also enforces that on a
|
|
|
+ * MAP_SHARED vma: there is no F_WRITE_SEAL and no further
|
|
|
+ * F_WRITE_SEAL can be taken until the vma is destroyed.
|
|
|
+ */
|
|
|
+ ret = -EPERM;
|
|
|
+ if (unlikely(!(cur->vm_flags & VM_MAYWRITE)))
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
/*
|
|
|
* If this vma contains ending address, and huge pages
|
|
|
* check alignment.
|
|
@@ -1406,6 +1419,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
|
|
BUG_ON(!vma_can_userfault(vma));
|
|
|
BUG_ON(vma->vm_userfaultfd_ctx.ctx &&
|
|
|
vma->vm_userfaultfd_ctx.ctx != ctx);
|
|
|
+ WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
|
|
|
|
|
|
/*
|
|
|
* Nothing to do: this vma is already registered into this
|
|
@@ -1552,6 +1566,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
|
|
|
cond_resched();
|
|
|
|
|
|
BUG_ON(!vma_can_userfault(vma));
|
|
|
+ WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
|
|
|
|
|
|
/*
|
|
|
* Nothing to do: this vma is already registered into this
|