Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/vma: convert __mmap_region() to use vma_flags_t

Update the mmap() implementation logic implemented in __mmap_region() and
functions invoked by it. The mmap_region() function converts its input
vm_flags_t parameter to a vma_flags_t value which it then passes to
__mmap_region() which uses the vma_flags_t value consistently from then
on.

As part of the change, we convert map_deny_write_exec() to using
vma_flags_t (it was incorrectly using unsigned long before), and place it
in vma.h, as it is only used internal to mm.

With this change, we eliminate the legacy is_shared_maywrite_vm_flags()
helper function which is now no longer required.

We are also able to update the MMAP_STATE() and VMG_MMAP_STATE() macros to
use the vma_flags_t value.

Finally, we update the VMA tests to reflect the change.

Link: https://lkml.kernel.org/r/1fc33a404c962f02da778da100387cc19bd62153.1774034900.git.ljs@kernel.org
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: "Borislav Petkov (AMD)" <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Chengming Zhou <chengming.zhou@linux.dev>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jann Horn <jannh@google.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Kees Cook <kees@kernel.org>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Ondrej Mosnacek <omosnace@redhat.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: Richard Weinberger <richard@nod.at>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Stephen Smalley <stephen.smalley.work@gmail.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Vineet Gupta <vgupta@kernel.org>
Cc: WANG Xuerui <kernel@xen0n.name>
Cc: Will Deacon <will@kernel.org>
Cc: xu xin <xu.xin16@zte.com.cn>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Lorenzo Stoakes (Oracle) and committed by
Andrew Morton
90cb921c a06eb2f8

+92 -107
+12 -6
include/linux/mm.h
··· 1522 1522 return vma->vm_flags & VM_ACCESS_FLAGS; 1523 1523 } 1524 1524 1525 - static inline bool is_shared_maywrite_vm_flags(vm_flags_t vm_flags) 1526 - { 1527 - return (vm_flags & (VM_SHARED | VM_MAYWRITE)) == 1528 - (VM_SHARED | VM_MAYWRITE); 1529 - } 1530 - 1531 1525 static inline bool is_shared_maywrite(const vma_flags_t *flags) 1532 1526 { 1533 1527 return vma_flags_test_all(flags, VMA_SHARED_BIT, VMA_MAYWRITE_BIT); ··· 4329 4335 4330 4336 #ifdef CONFIG_MMU 4331 4337 pgprot_t vm_get_page_prot(vm_flags_t vm_flags); 4338 + 4339 + static inline pgprot_t vma_get_page_prot(vma_flags_t vma_flags) 4340 + { 4341 + const vm_flags_t vm_flags = vma_flags_to_legacy(vma_flags); 4342 + 4343 + return vm_get_page_prot(vm_flags); 4344 + } 4345 + 4332 4346 void vma_set_page_prot(struct vm_area_struct *vma); 4333 4347 #else 4334 4348 static inline pgprot_t vm_get_page_prot(vm_flags_t vm_flags) 4349 + { 4350 + return __pgprot(0); 4351 + } 4352 + static inline pgprot_t vma_get_page_prot(vma_flags_t vma_flags) 4335 4353 { 4336 4354 return __pgprot(0); 4337 4355 }
-49
include/linux/mman.h
··· 170 170 } 171 171 #define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported 172 172 #endif 173 - 174 - /* 175 - * Denies creating a writable executable mapping or gaining executable permissions. 176 - * 177 - * This denies the following: 178 - * 179 - * a) mmap(PROT_WRITE | PROT_EXEC) 180 - * 181 - * b) mmap(PROT_WRITE) 182 - * mprotect(PROT_EXEC) 183 - * 184 - * c) mmap(PROT_WRITE) 185 - * mprotect(PROT_READ) 186 - * mprotect(PROT_EXEC) 187 - * 188 - * But allows the following: 189 - * 190 - * d) mmap(PROT_READ | PROT_EXEC) 191 - * mmap(PROT_READ | PROT_EXEC | PROT_BTI) 192 - * 193 - * This is only applicable if the user has set the Memory-Deny-Write-Execute 194 - * (MDWE) protection mask for the current process. 195 - * 196 - * @old specifies the VMA flags the VMA originally possessed, and @new the ones 197 - * we propose to set. 198 - * 199 - * Return: false if proposed change is OK, true if not ok and should be denied. 200 - */ 201 - static inline bool map_deny_write_exec(unsigned long old, unsigned long new) 202 - { 203 - /* If MDWE is disabled, we have nothing to deny. */ 204 - if (!mm_flags_test(MMF_HAS_MDWE, current->mm)) 205 - return false; 206 - 207 - /* If the new VMA is not executable, we have nothing to deny. */ 208 - if (!(new & VM_EXEC)) 209 - return false; 210 - 211 - /* Under MDWE we do not accept newly writably executable VMAs... */ 212 - if (new & VM_WRITE) 213 - return true; 214 - 215 - /* ...nor previously non-executable VMAs becoming executable. */ 216 - if (!(old & VM_EXEC)) 217 - return true; 218 - 219 - return false; 220 - } 221 - 222 173 #endif /* _LINUX_MMAN_H */
+3 -1
mm/mprotect.c
··· 882 882 tmp = vma->vm_start; 883 883 for_each_vma_range(vmi, vma, end) { 884 884 vm_flags_t mask_off_old_flags; 885 + vma_flags_t new_vma_flags; 885 886 vm_flags_t newflags; 886 887 int new_vma_pkey; 887 888 ··· 905 904 new_vma_pkey = arch_override_mprotect_pkey(vma, prot, pkey); 906 905 newflags = calc_vm_prot_bits(prot, new_vma_pkey); 907 906 newflags |= (vma->vm_flags & ~mask_off_old_flags); 907 + new_vma_flags = legacy_to_vma_flags(newflags); 908 908 909 909 /* newflags >> 4 shift VM_MAY% in place of VM_% */ 910 910 if ((newflags & ~(newflags >> 4)) & VM_ACCESS_FLAGS) { ··· 913 911 break; 914 912 } 915 913 916 - if (map_deny_write_exec(vma->vm_flags, newflags)) { 914 + if (map_deny_write_exec(&vma->flags, &new_vma_flags)) { 917 915 error = -EACCES; 918 916 break; 919 917 }
+13 -12
mm/vma.c
··· 44 44 bool file_doesnt_need_get :1; 45 45 }; 46 46 47 - #define MMAP_STATE(name, mm_, vmi_, addr_, len_, pgoff_, vm_flags_, file_) \ 47 + #define MMAP_STATE(name, mm_, vmi_, addr_, len_, pgoff_, vma_flags_, file_) \ 48 48 struct mmap_state name = { \ 49 49 .mm = mm_, \ 50 50 .vmi = vmi_, \ ··· 52 52 .end = (addr_) + (len_), \ 53 53 .pgoff = pgoff_, \ 54 54 .pglen = PHYS_PFN(len_), \ 55 - .vm_flags = vm_flags_, \ 55 + .vma_flags = vma_flags_, \ 56 56 .file = file_, \ 57 - .page_prot = vm_get_page_prot(vm_flags_), \ 57 + .page_prot = vma_get_page_prot(vma_flags_), \ 58 58 } 59 59 60 60 #define VMG_MMAP_STATE(name, map_, vma_) \ ··· 63 63 .vmi = (map_)->vmi, \ 64 64 .start = (map_)->addr, \ 65 65 .end = (map_)->end, \ 66 - .vm_flags = (map_)->vm_flags, \ 66 + .vma_flags = (map_)->vma_flags, \ 67 67 .pgoff = (map_)->pgoff, \ 68 68 .file = (map_)->file, \ 69 69 .prev = (map_)->prev, \ ··· 2746 2746 } 2747 2747 2748 2748 static unsigned long __mmap_region(struct file *file, unsigned long addr, 2749 - unsigned long len, vm_flags_t vm_flags, unsigned long pgoff, 2750 - struct list_head *uf) 2749 + unsigned long len, vma_flags_t vma_flags, 2750 + unsigned long pgoff, struct list_head *uf) 2751 2751 { 2752 2752 struct mm_struct *mm = current->mm; 2753 2753 struct vm_area_struct *vma = NULL; 2754 2754 bool have_mmap_prepare = file && file->f_op->mmap_prepare; 2755 2755 VMA_ITERATOR(vmi, mm, addr); 2756 - MMAP_STATE(map, mm, &vmi, addr, len, pgoff, vm_flags, file); 2756 + MMAP_STATE(map, mm, &vmi, addr, len, pgoff, vma_flags, file); 2757 2757 struct vm_area_desc desc = { 2758 2758 .mm = mm, 2759 2759 .file = file, ··· 2837 2837 * been performed. 2838 2838 */ 2839 2839 unsigned long mmap_region(struct file *file, unsigned long addr, 2840 - unsigned long len, vm_flags_t vm_flags, unsigned long pgoff, 2841 - struct list_head *uf) 2840 + unsigned long len, vm_flags_t vm_flags, 2841 + unsigned long pgoff, struct list_head *uf) 2842 2842 { 2843 2843 unsigned long ret; 2844 2844 bool writable_file_mapping = false; 2845 + const vma_flags_t vma_flags = legacy_to_vma_flags(vm_flags); 2845 2846 2846 2847 mmap_assert_write_locked(current->mm); 2847 2848 2848 2849 /* Check to see if MDWE is applicable. */ 2849 - if (map_deny_write_exec(vm_flags, vm_flags)) 2850 + if (map_deny_write_exec(&vma_flags, &vma_flags)) 2850 2851 return -EACCES; 2851 2852 2852 2853 /* Allow architectures to sanity-check the vm_flags. */ ··· 2855 2854 return -EINVAL; 2856 2855 2857 2856 /* Map writable and ensure this isn't a sealed memfd. */ 2858 - if (file && is_shared_maywrite_vm_flags(vm_flags)) { 2857 + if (file && is_shared_maywrite(&vma_flags)) { 2859 2858 int error = mapping_map_writable(file->f_mapping); 2860 2859 2861 2860 if (error) ··· 2863 2862 writable_file_mapping = true; 2864 2863 } 2865 2864 2866 - ret = __mmap_region(file, addr, len, vm_flags, pgoff, uf); 2865 + ret = __mmap_region(file, addr, len, vma_flags, pgoff, uf); 2867 2866 2868 2867 /* Clear our write mapping regardless of error. */ 2869 2868 if (writable_file_mapping)
+51
mm/vma.h
··· 704 704 int relocate_vma_down(struct vm_area_struct *vma, unsigned long shift); 705 705 #endif 706 706 707 + #ifdef CONFIG_MMU 708 + /* 709 + * Denies creating a writable executable mapping or gaining executable permissions. 710 + * 711 + * This denies the following: 712 + * 713 + * a) mmap(PROT_WRITE | PROT_EXEC) 714 + * 715 + * b) mmap(PROT_WRITE) 716 + * mprotect(PROT_EXEC) 717 + * 718 + * c) mmap(PROT_WRITE) 719 + * mprotect(PROT_READ) 720 + * mprotect(PROT_EXEC) 721 + * 722 + * But allows the following: 723 + * 724 + * d) mmap(PROT_READ | PROT_EXEC) 725 + * mmap(PROT_READ | PROT_EXEC | PROT_BTI) 726 + * 727 + * This is only applicable if the user has set the Memory-Deny-Write-Execute 728 + * (MDWE) protection mask for the current process. 729 + * 730 + * @old specifies the VMA flags the VMA originally possessed, and @new the ones 731 + * we propose to set. 732 + * 733 + * Return: false if proposed change is OK, true if not ok and should be denied. 734 + */ 735 + static inline bool map_deny_write_exec(const vma_flags_t *old, 736 + const vma_flags_t *new) 737 + { 738 + /* If MDWE is disabled, we have nothing to deny. */ 739 + if (!mm_flags_test(MMF_HAS_MDWE, current->mm)) 740 + return false; 741 + 742 + /* If the new VMA is not executable, we have nothing to deny. */ 743 + if (!vma_flags_test(new, VMA_EXEC_BIT)) 744 + return false; 745 + 746 + /* Under MDWE we do not accept newly writably executable VMAs... */ 747 + if (vma_flags_test(new, VMA_WRITE_BIT)) 748 + return true; 749 + 750 + /* ...nor previously non-executable VMAs becoming executable. */ 751 + if (!vma_flags_test(old, VMA_EXEC_BIT)) 752 + return true; 753 + 754 + return false; 755 + } 756 + #endif 757 + 707 758 #endif /* __MM_VMA_H */
+7 -27
tools/testing/vma/include/dup.h
··· 1124 1124 #define vma_desc_clear_flags(desc, ...) \ 1125 1125 vma_desc_clear_flags_mask(desc, mk_vma_flags(__VA_ARGS__)) 1126 1126 1127 - static inline bool is_shared_maywrite_vm_flags(vm_flags_t vm_flags) 1128 - { 1129 - return (vm_flags & (VM_SHARED | VM_MAYWRITE)) == 1130 - (VM_SHARED | VM_MAYWRITE); 1131 - } 1132 - 1133 1127 static inline bool is_shared_maywrite(const vma_flags_t *flags) 1134 1128 { 1135 1129 return vma_flags_test_all(flags, VMA_SHARED_BIT, VMA_MAYWRITE_BIT); ··· 1440 1446 return locked_pages <= limit_pages; 1441 1447 } 1442 1448 1443 - static inline bool map_deny_write_exec(unsigned long old, unsigned long new) 1444 - { 1445 - /* If MDWE is disabled, we have nothing to deny. */ 1446 - if (mm_flags_test(MMF_HAS_MDWE, current->mm)) 1447 - return false; 1448 - 1449 - /* If the new VMA is not executable, we have nothing to deny. */ 1450 - if (!(new & VM_EXEC)) 1451 - return false; 1452 - 1453 - /* Under MDWE we do not accept newly writably executable VMAs... */ 1454 - if (new & VM_WRITE) 1455 - return true; 1456 - 1457 - /* ...nor previously non-executable VMAs becoming executable. */ 1458 - if (!(old & VM_EXEC)) 1459 - return true; 1460 - 1461 - return false; 1462 - } 1463 - 1464 1449 static inline int mapping_map_writable(struct address_space *mapping) 1465 1450 { 1466 1451 return atomic_inc_unless_negative(&mapping->i_mmap_writable) ? ··· 1491 1518 #ifndef pgtable_supports_soft_dirty 1492 1519 #define pgtable_supports_soft_dirty() IS_ENABLED(CONFIG_MEM_SOFT_DIRTY) 1493 1520 #endif 1521 + 1522 + static inline pgprot_t vma_get_page_prot(vma_flags_t vma_flags) 1523 + { 1524 + const vm_flags_t vm_flags = vma_flags_to_legacy(vma_flags); 1525 + 1526 + return vm_get_page_prot(vm_flags); 1527 + }
+6 -12
tools/testing/vma/tests/mmap.c
··· 2 2 3 3 static bool test_mmap_region_basic(void) 4 4 { 5 + const vma_flags_t vma_flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, 6 + VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT); 5 7 struct mm_struct mm = {}; 6 8 unsigned long addr; 7 9 struct vm_area_struct *vma; ··· 12 10 current->mm = &mm; 13 11 14 12 /* Map at 0x300000, length 0x3000. */ 15 - addr = __mmap_region(NULL, 0x300000, 0x3000, 16 - VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE, 17 - 0x300, NULL); 13 + addr = __mmap_region(NULL, 0x300000, 0x3000, vma_flags, 0x300, NULL); 18 14 ASSERT_EQ(addr, 0x300000); 19 15 20 16 /* Map at 0x250000, length 0x3000. */ 21 - addr = __mmap_region(NULL, 0x250000, 0x3000, 22 - VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE, 23 - 0x250, NULL); 17 + addr = __mmap_region(NULL, 0x250000, 0x3000, vma_flags, 0x250, NULL); 24 18 ASSERT_EQ(addr, 0x250000); 25 19 26 20 /* Map at 0x303000, merging to 0x300000 of length 0x6000. */ 27 - addr = __mmap_region(NULL, 0x303000, 0x3000, 28 - VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE, 29 - 0x303, NULL); 21 + addr = __mmap_region(NULL, 0x303000, 0x3000, vma_flags, 0x303, NULL); 30 22 ASSERT_EQ(addr, 0x303000); 31 23 32 24 /* Map at 0x24d000, merging to 0x250000 of length 0x6000. */ 33 - addr = __mmap_region(NULL, 0x24d000, 0x3000, 34 - VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE, 35 - 0x24d, NULL); 25 + addr = __mmap_region(NULL, 0x24d000, 0x3000, vma_flags, 0x24d, NULL); 36 26 ASSERT_EQ(addr, 0x24d000); 37 27 38 28 ASSERT_EQ(mm.map_count, 2);