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: refactor arch_calc_vm_flag_bits() and arm64 MTE handling

Currently MTE is permitted in two circumstances (desiring to use MTE
having been specified by the VM_MTE flag) - where MAP_ANONYMOUS is
specified, as checked by arch_calc_vm_flag_bits() and actualised by
setting the VM_MTE_ALLOWED flag, or if the file backing the mapping is
shmem, in which case we set VM_MTE_ALLOWED in shmem_mmap() when the mmap
hook is activated in mmap_region().

The function that checks that, if VM_MTE is set, VM_MTE_ALLOWED is also
set is the arm64 implementation of arch_validate_flags().

Unfortunately, we intend to refactor mmap_region() to perform this check
earlier, meaning that in the case of a shmem backing we will not have
invoked shmem_mmap() yet, causing the mapping to fail spuriously.

It is inappropriate to set this architecture-specific flag in general mm
code anyway, so a sensible resolution of this issue is to instead move the
check somewhere else.

We resolve this by setting VM_MTE_ALLOWED much earlier in do_mmap(), via
the arch_calc_vm_flag_bits() call.

This is an appropriate place to do this as we already check for the
MAP_ANONYMOUS case here, and the shmem file case is simply a variant of
the same idea - we permit RAM-backed memory.

This requires a modification to the arch_calc_vm_flag_bits() signature to
pass in a pointer to the struct file associated with the mapping, however
this is not too egregious as this is only used by two architectures anyway
- arm64 and parisc.

So this patch performs this adjustment and removes the unnecessary
assignment of VM_MTE_ALLOWED in shmem_mmap().

[akpm@linux-foundation.org: fix whitespace, per Catalin]
Link: https://lkml.kernel.org/r/ec251b20ba1964fb64cf1607d2ad80c47f3873df.1730224667.git.lorenzo.stoakes@oracle.com
Fixes: deb0f6562884 ("mm/mmap: undo ->mmap() when arch_validate_flags() fails")
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
Reported-by: Jann Horn <jannh@google.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Andreas Larsson <andreas@gaisler.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Helge Deller <deller@gmx.de>
Cc: James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Peter Xu <peterx@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Lorenzo Stoakes and committed by
Andrew Morton
5baf8b03 0fb4a7ad

+16 -13
+7 -3
arch/arm64/include/asm/mman.h
··· 6 6 7 7 #ifndef BUILD_VDSO 8 8 #include <linux/compiler.h> 9 + #include <linux/fs.h> 10 + #include <linux/shmem_fs.h> 9 11 #include <linux/types.h> 10 12 11 13 static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot, ··· 33 31 } 34 32 #define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey) 35 33 36 - static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags) 34 + static inline unsigned long arch_calc_vm_flag_bits(struct file *file, 35 + unsigned long flags) 37 36 { 38 37 /* 39 38 * Only allow MTE on anonymous mappings as these are guaranteed to be 40 39 * backed by tags-capable memory. The vm_flags may be overridden by a 41 40 * filesystem supporting MTE (RAM-based). 42 41 */ 43 - if (system_supports_mte() && (flags & MAP_ANONYMOUS)) 42 + if (system_supports_mte() && 43 + ((flags & MAP_ANONYMOUS) || shmem_file(file))) 44 44 return VM_MTE_ALLOWED; 45 45 46 46 return 0; 47 47 } 48 - #define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags) 48 + #define arch_calc_vm_flag_bits(file, flags) arch_calc_vm_flag_bits(file, flags) 49 49 50 50 static inline bool arch_validate_prot(unsigned long prot, 51 51 unsigned long addr __always_unused)
+3 -2
arch/parisc/include/asm/mman.h
··· 2 2 #ifndef __ASM_MMAN_H__ 3 3 #define __ASM_MMAN_H__ 4 4 5 + #include <linux/fs.h> 5 6 #include <uapi/asm/mman.h> 6 7 7 8 /* PARISC cannot allow mdwe as it needs writable stacks */ ··· 12 11 } 13 12 #define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported 14 13 15 - static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags) 14 + static inline unsigned long arch_calc_vm_flag_bits(struct file *file, unsigned long flags) 16 15 { 17 16 /* 18 17 * The stack on parisc grows upwards, so if userspace requests memory ··· 24 23 25 24 return 0; 26 25 } 27 - #define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags) 26 + #define arch_calc_vm_flag_bits(file, flags) arch_calc_vm_flag_bits(file, flags) 28 27 29 28 #endif /* __ASM_MMAN_H__ */
+4 -3
include/linux/mman.h
··· 2 2 #ifndef _LINUX_MMAN_H 3 3 #define _LINUX_MMAN_H 4 4 5 + #include <linux/fs.h> 5 6 #include <linux/mm.h> 6 7 #include <linux/percpu_counter.h> 7 8 ··· 95 94 #endif 96 95 97 96 #ifndef arch_calc_vm_flag_bits 98 - #define arch_calc_vm_flag_bits(flags) 0 97 + #define arch_calc_vm_flag_bits(file, flags) 0 99 98 #endif 100 99 101 100 #ifndef arch_validate_prot ··· 152 151 * Combine the mmap "flags" argument into "vm_flags" used internally. 153 152 */ 154 153 static inline unsigned long 155 - calc_vm_flag_bits(unsigned long flags) 154 + calc_vm_flag_bits(struct file *file, unsigned long flags) 156 155 { 157 156 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | 158 157 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) | 159 158 _calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) | 160 159 _calc_vm_trans(flags, MAP_STACK, VM_NOHUGEPAGE) | 161 - arch_calc_vm_flag_bits(flags); 160 + arch_calc_vm_flag_bits(file, flags); 162 161 } 163 162 164 163 unsigned long vm_commit_limit(void);
+1 -1
mm/mmap.c
··· 344 344 * to. we assume access permissions have been handled by the open 345 345 * of the memory object, so we don't do any here. 346 346 */ 347 - vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) | 347 + vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(file, flags) | 348 348 mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; 349 349 350 350 /* Obtain the address to map to. we verify (or select) it and ensure
+1 -1
mm/nommu.c
··· 842 842 { 843 843 unsigned long vm_flags; 844 844 845 - vm_flags = calc_vm_prot_bits(prot, 0) | calc_vm_flag_bits(flags); 845 + vm_flags = calc_vm_prot_bits(prot, 0) | calc_vm_flag_bits(file, flags); 846 846 847 847 if (!file) { 848 848 /*
-3
mm/shmem.c
··· 2733 2733 if (ret) 2734 2734 return ret; 2735 2735 2736 - /* arm64 - allow memory tagging on RAM-based files */ 2737 - vm_flags_set(vma, VM_MTE_ALLOWED); 2738 - 2739 2736 file_accessed(file); 2740 2737 /* This is anonymous shared memory if it is unlinked at the time of mmap */ 2741 2738 if (inode->i_nlink)