We need to validate that the address and length of a MAP_FIXED request are suitable for hugetlb pages. i386/mm/hugetlbpage.c | 12 ++++++++++++ ia64/mm/hugetlbpage.c | 12 ++++++++++++ sparc64/mm/hugetlbpage.c | 12 ++++++++++++ x86_64/mm/hugetlbpage.c | 12 ++++++++++++ linux/hugetlb.h | 2 ++ mmap.c | 13 +++++++++++-- 6 files changed, 61 insertions(+), 2 deletions(-) diff -puN arch/i386/mm/hugetlbpage.c~hugepage-address-validation arch/i386/mm/hugetlbpage.c --- 25/arch/i386/mm/hugetlbpage.c~hugepage-address-validation 2003-02-08 00:34:42.000000000 -0800 +++ 25-akpm/arch/i386/mm/hugetlbpage.c 2003-02-08 00:34:42.000000000 -0800 @@ -88,6 +88,18 @@ static void set_huge_pte(struct mm_struc set_pte(page_table, entry); } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { diff -puN arch/ia64/mm/hugetlbpage.c~hugepage-address-validation arch/ia64/mm/hugetlbpage.c --- 25/arch/ia64/mm/hugetlbpage.c~hugepage-address-validation 2003-02-08 00:34:42.000000000 -0800 +++ 25-akpm/arch/ia64/mm/hugetlbpage.c 2003-02-08 00:34:42.000000000 -0800 @@ -96,6 +96,18 @@ set_huge_pte (struct mm_struct *mm, stru return; } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { diff -puN arch/sparc64/mm/hugetlbpage.c~hugepage-address-validation arch/sparc64/mm/hugetlbpage.c --- 25/arch/sparc64/mm/hugetlbpage.c~hugepage-address-validation 2003-02-08 00:34:42.000000000 -0800 +++ 25-akpm/arch/sparc64/mm/hugetlbpage.c 2003-02-08 00:34:42.000000000 -0800 @@ -232,6 +232,18 @@ out_error: return -1; } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { diff -puN arch/x86_64/mm/hugetlbpage.c~hugepage-address-validation arch/x86_64/mm/hugetlbpage.c --- 25/arch/x86_64/mm/hugetlbpage.c~hugepage-address-validation 2003-02-08 00:34:42.000000000 -0800 +++ 25-akpm/arch/x86_64/mm/hugetlbpage.c 2003-02-08 00:34:42.000000000 -0800 @@ -86,6 +86,18 @@ static void set_huge_pte(struct mm_struc set_pte(page_table, entry); } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) diff -puN include/linux/hugetlb.h~hugepage-address-validation include/linux/hugetlb.h --- 25/include/linux/hugetlb.h~hugepage-address-validation 2003-02-08 00:34:42.000000000 -0800 +++ 25-akpm/include/linux/hugetlb.h 2003-02-08 00:34:42.000000000 -0800 @@ -26,6 +26,7 @@ struct vm_area_struct *hugepage_vma(stru unsigned long address); struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write); +int is_aligned_hugepage_range(unsigned long addr, unsigned long len); int pmd_huge(pmd_t pmd); extern int htlbpage_max; @@ -56,6 +57,7 @@ static inline int is_vm_hugetlb_page(str #define hugepage_vma(mm, addr) 0 #define mark_mm_hugetlb(mm, vma) do { } while (0) #define follow_huge_pmd(mm, addr, pmd, write) 0 +#define is_aligned_hugepage_range(addr, len) 0 #define pmd_huge(x) 0 #ifndef HPAGE_MASK diff -puN mm/mmap.c~hugepage-address-validation mm/mmap.c --- 25/mm/mmap.c~hugepage-address-validation 2003-02-08 00:34:42.000000000 -0800 +++ 25-akpm/mm/mmap.c 2003-02-08 00:34:42.000000000 -0800 @@ -801,6 +801,13 @@ get_unmapped_area(struct file *file, uns return -ENOMEM; if (addr & ~PAGE_MASK) return -EINVAL; + if (is_file_hugepages(file)) { + unsigned long ret; + + ret = is_aligned_hugepage_range(addr, len); + if (ret) + return ret; + } return addr; } @@ -1224,8 +1231,10 @@ int do_munmap(struct mm_struct *mm, unsi /* we have start < mpnt->vm_end */ if (is_vm_hugetlb_page(mpnt)) { - if ((start & ~HPAGE_MASK) || (len & ~HPAGE_MASK)) - return -EINVAL; + int ret = is_aligned_hugepage_range(start, len); + + if (ret) + return ret; } /* if it doesn't overlap, we have nothing.. */ _