From: Alison Schofield <[email protected]>

Memory encryption is only supported for mappings that are ANONYMOUS.
Test the VMA's in an encrypt_mprotect() request to make sure they all
meet that requirement before encrypting any.

The encrypt_mprotect syscall will return -EINVAL and will not encrypt
any VMA's if this check fails.

Signed-off-by: Alison Schofield <[email protected]>
Signed-off-by: Kirill A. Shutemov <[email protected]>
---
 mm/mprotect.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/mm/mprotect.c b/mm/mprotect.c
index 518d75582e7b..4b079e1b2d6f 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -347,6 +347,24 @@ static int prot_none_walk(struct vm_area_struct *vma, 
unsigned long start,
        return walk_page_range(start, end, &prot_none_walk);
 }
 
+/*
+ * Encrypted mprotect is only supported on anonymous mappings.
+ * If this test fails on any single VMA, the entire mprotect
+ * request fails.
+ */
+static bool mem_supports_encryption(struct vm_area_struct *vma, unsigned long 
end)
+{
+       struct vm_area_struct *test_vma = vma;
+
+       do {
+               if (!vma_is_anonymous(test_vma))
+                       return false;
+
+               test_vma = test_vma->vm_next;
+       } while (test_vma && test_vma->vm_start < end);
+       return true;
+}
+
 int
 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
               unsigned long start, unsigned long end, unsigned long newflags,
@@ -533,6 +551,12 @@ static int do_mprotect_ext(unsigned long start, size_t len,
                                goto out;
                }
        }
+
+       if (keyid > 0 && !mem_supports_encryption(vma, end)) {
+               error = -EINVAL;
+               goto out;
+       }
+
        if (start > vma->vm_start)
                prev = vma;
 
-- 
2.21.0

Reply via email to