]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mseal: Replace can_modify_mm_madv with a vma variant
authorPedro Falcato <pedro.falcato@gmail.com>
Sat, 17 Aug 2024 00:18:32 +0000 (01:18 +0100)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Mon, 19 Aug 2024 20:11:54 +0000 (16:11 -0400)
Replace can_modify_mm_madv() with a single vma variant, and associated
checks in madvise.

While we're at it, also invert the order of checks in:
 if (unlikely(is_ro_anon(vma) && !can_modify_vma(vma))

Checking if we can modify the vma itself (through vm_flags) is
certainly cheaper than is_ro_anon() due to arch_vma_access_permitted()
looking at e.g pkeys registers (with extra branches) in some
architectures.

This patch allows for partial madvise success when finding a sealed VMA,
which historically has been allowed in Linux.

Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com>
mm/internal.h
mm/madvise.c
mm/mseal.c
mm/vma.h

index cde62b16b71c688092bd0b15b3acb57424aad88a..8ebfefc7015542e974412f5549c49cafa6d6f697 100644 (file)
@@ -1370,8 +1370,6 @@ static inline int can_do_mseal(unsigned long flags)
 
 bool can_modify_mm(struct mm_struct *mm, unsigned long start,
                unsigned long end);
-bool can_modify_mm_madv(struct mm_struct *mm, unsigned long start,
-               unsigned long end, int behavior);
 #else
 static inline int can_do_mseal(unsigned long flags)
 {
index 89089d84f8df8712fc1f0e86a4e07258685e0554..4e64770be16c9852a50a0a27c39a62b53edf650b 100644 (file)
@@ -1031,6 +1031,9 @@ static int madvise_vma_behavior(struct vm_area_struct *vma,
        struct anon_vma_name *anon_name;
        unsigned long new_flags = vma->vm_flags;
 
+       if (unlikely(!can_modify_vma_madv(vma, behavior)))
+               return -EPERM;
+
        switch (behavior) {
        case MADV_REMOVE:
                return madvise_remove(vma, prev, start, end);
@@ -1448,15 +1451,6 @@ int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int beh
        start = untagged_addr_remote(mm, start);
        end = start + len;
 
-       /*
-        * Check if the address range is sealed for do_madvise().
-        * can_modify_mm_madv assumes we have acquired the lock on MM.
-        */
-       if (unlikely(!can_modify_mm_madv(mm, start, end, behavior))) {
-               error = -EPERM;
-               goto out;
-       }
-
        blk_start_plug(&plug);
        switch (behavior) {
        case MADV_POPULATE_READ:
@@ -1470,7 +1464,6 @@ int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int beh
        }
        blk_finish_plug(&plug);
 
-out:
        if (write)
                mmap_write_unlock(mm);
        else
index 2170e2139ca0a9143a942e2de41ced8181ebebd6..fdd1666344fac240d30b09cd3ec74344b91cef00 100644 (file)
@@ -75,24 +75,15 @@ bool can_modify_mm(struct mm_struct *mm, unsigned long start, unsigned long end)
 }
 
 /*
- * Check if the vmas of a memory range are allowed to be modified by madvise.
- * the memory ranger can have a gap (unallocated memory).
- * return true, if it is allowed.
+ * Check if a vma is allowed to be modified by madvise.
  */
-bool can_modify_mm_madv(struct mm_struct *mm, unsigned long start, unsigned long end,
-               int behavior)
+bool can_modify_vma_madv(struct vm_area_struct *vma, int behavior)
 {
-       struct vm_area_struct *vma;
-
-       VMA_ITERATOR(vmi, mm, start);
-
        if (!is_madv_discard(behavior))
                return true;
 
-       /* going through each vma to check. */
-       for_each_vma_range(vmi, vma, end)
-               if (unlikely(is_ro_anon(vma) && !can_modify_vma(vma)))
-                       return false;
+       if (unlikely(!can_modify_vma(vma) && is_ro_anon(vma)))
+               return false;
 
        /* Allow by default. */
        return true;
index e979015cc7fc27ffe6869f7f23a83c433ff15e67..da31d0f6215721fd1069531d6bd2c1f875a1c48b 100644 (file)
--- a/mm/vma.h
+++ b/mm/vma.h
@@ -380,6 +380,8 @@ static inline bool can_modify_vma(struct vm_area_struct *vma)
        return true;
 }
 
+bool can_modify_vma_madv(struct vm_area_struct *vma, int behavior);
+
 #else
 
 static inline bool can_modify_vma(struct vm_area_struct *vma)
@@ -387,6 +389,11 @@ static inline bool can_modify_vma(struct vm_area_struct *vma)
        return true;
 }
 
+static inline bool can_modify_vma_madv(struct vm_area_struct *vma, int behavior)
+{
+       return true;
+}
+
 #endif
 
 #endif /* __MM_VMA_H */