Le 12/03/2024 à 23:28, Rick Edgecombe a écrit : > When memory is being placed, mmap() will take care to respect the guard > gaps of certain types of memory (VM_SHADOWSTACK, VM_GROWSUP and > VM_GROWSDOWN). In order to ensure guard gaps between mappings, mmap() > needs to consider two things: > 1. That the new mapping isn’t placed in an any existing mappings guard > gaps. > 2. That the new mapping isn’t placed such that any existing mappings > are not in *its* guard gaps. > > The long standing behavior of mmap() is to ensure 1, but not take any care > around 2. So for example, if there is a PAGE_SIZE free area, and a > mmap() with a PAGE_SIZE size, and a type that has a guard gap is being > placed, mmap() may place the shadow stack in the PAGE_SIZE free area. Then > the mapping that is supposed to have a guard gap will not have a gap to > the adjacent VMA. > > Add x86 arch implementations of arch_get_unmapped_area_vmflags/_topdown() > so future changes can allow the guard gap of type of vma being placed to > be taken into account. This will be used for shadow stack memory. > > Signed-off-by: Rick Edgecombe <rick.p.edgecombe@xxxxxxxxx> > --- > v3: > - Commit log grammar > > v2: > - Remove unnecessary added extern > --- > arch/x86/include/asm/pgtable_64.h | 1 + > arch/x86/kernel/sys_x86_64.c | 25 ++++++++++++++++++++----- > 2 files changed, 21 insertions(+), 5 deletions(-) > > diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h > index 24af25b1551a..13dcaf436efd 100644 > --- a/arch/x86/include/asm/pgtable_64.h > +++ b/arch/x86/include/asm/pgtable_64.h > @@ -244,6 +244,7 @@ extern void cleanup_highmap(void); > > #define HAVE_ARCH_UNMAPPED_AREA > #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN > +#define HAVE_ARCH_UNMAPPED_AREA_VMFLAGS > > #define PAGE_AGP PAGE_KERNEL_NOCACHE > #define HAVE_PAGE_AGP 1 > diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c > index b3278e4f7e59..d6fbc4dd08ef 100644 > --- a/arch/x86/kernel/sys_x86_64.c > +++ b/arch/x86/kernel/sys_x86_64.c > @@ -120,8 +120,8 @@ static void find_start_end(unsigned long addr, unsigned long flags, > } > > unsigned long > -arch_get_unmapped_area(struct file *filp, unsigned long addr, > - unsigned long len, unsigned long pgoff, unsigned long flags) > +arch_get_unmapped_area_vmflags(struct file *filp, unsigned long addr, unsigned long len, > + unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags) > { > struct mm_struct *mm = current->mm; > struct vm_area_struct *vma; > @@ -156,9 +156,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, > } > > unsigned long > -arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, > - const unsigned long len, const unsigned long pgoff, > - const unsigned long flags) > +arch_get_unmapped_area_topdown_vmflags(struct file *filp, unsigned long addr0, > + unsigned long len, unsigned long pgoff, > + unsigned long flags, vm_flags_t vm_flags) > { > struct vm_area_struct *vma; > struct mm_struct *mm = current->mm; > @@ -227,3 +227,18 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, > */ > return arch_get_unmapped_area(filp, addr0, len, pgoff, flags); > } > + > +unsigned long > +arch_get_unmapped_area(struct file *filp, unsigned long addr, > + unsigned long len, unsigned long pgoff, unsigned long flags) > +{ > + return arch_get_unmapped_area_vmflags(filp, addr, len, pgoff, flags, 0); > +} > + > +unsigned long > +arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, > + const unsigned long len, const unsigned long pgoff, > + const unsigned long flags) > +{ > + return arch_get_unmapped_area_topdown_vmflags(filp, addr, len, pgoff, flags, 0); > +} Wouldn't it be better to define those two as static inlines ?