From d378f3ab39d04dc9b6ad9c366d7bf88ca97a5385 Mon Sep 17 00:00:00 2001 From: Kalesh Singh Date: Tue, 24 Sep 2024 23:34:05 +0000 Subject: [PATCH] ANDROID: 16K: Fixup padding vm_flags bits on VMA splits In some cases VMAs are split without the mmap write lock held; later the lock is taken to fixup vm_flags of the original VMA. Since some uppper bits of vm_flags are used to encode the ELF padding ranges, they need to be modified on splits. This is usually handled correctly by __split_vma(). However in the above case, the flags get over witten later under the write lock. Preserve vm_flag bits on reset to correctly represent padding. Bug: 383389169 Bug: 357901498 Change-Id: I1cb75419e614791a47cbdb0341373f619daf0bf2 Signed-off-by: Kalesh Singh --- include/linux/mm.h | 5 +++++ mm/mlock.c | 2 +- mm/mprotect.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 71cf4d4365f5..07f433fab267 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -971,6 +972,8 @@ static inline void vm_flags_reset(struct vm_area_struct *vma, vm_flags_t flags) { vma_assert_write_locked(vma); + /* Preserve padding flags */ + flags = vma_pad_fixup_flags(vma, flags); vm_flags_init(vma, flags); } @@ -978,6 +981,8 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma, vm_flags_t flags) { vma_assert_write_locked(vma); + /* Preserve padding flags */ + flags = vma_pad_fixup_flags(vma, flags); WRITE_ONCE(ACCESS_PRIVATE(vma, __vm_flags), flags); } diff --git a/mm/mlock.c b/mm/mlock.c index a76ef7603bf9..431293873a09 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -504,7 +504,7 @@ static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma, if ((newflags & VM_LOCKED) && (oldflags & VM_LOCKED)) { /* No work to do, and mlocking twice would be wrong */ vma_start_write(vma); - vm_flags_reset(vma, vma_pad_fixup_flags(vma, newflags)); + vm_flags_reset(vma, newflags); } else { mlock_vma_pages_range(vma, start, end, newflags); } diff --git a/mm/mprotect.c b/mm/mprotect.c index 7ba711f528fa..264650ba8a5c 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -678,7 +678,7 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb, * held in write mode. */ vma_start_write(vma); - vm_flags_reset(vma, vma_pad_fixup_flags(vma, newflags)); + vm_flags_reset(vma, newflags); if (vma_wants_manual_pte_write_upgrade(vma)) mm_cp_flags |= MM_CP_TRY_CHANGE_WRITABLE; vma_set_page_prot(vma);