fs/hugetlbfs/inode.c: Ensure generic_hugetlb_get_unmapped_area() returns higher address than mmap_min_addr
Subsystems (2)
PATCH 1/1 fs/hugetlbfs/inode.c: Ensure generic_hugetlb_get_unmapped_area() returns higher address than mmap_min_addr
generic_hugetlb_get_unmapped_area() was returning an address less than mmap_min_addr if the mmap argument addr, after alignment, was less than mmap_min_addr, causing mmap to fail.
This is because current generic_hugetlb_get_unmapped_area() code does not take into account mmap_min_addr.
This patch ensures that generic_hugetlb_get_unmapped_area() always returns an address that is greater than mmap_min_addr.
How to reproduce
================
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#define HUGEPAGE_SIZE (16 * 1024 * 1024)
int main() {
void *addr = mmap((void *)-1, HUGEPAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
if (addr == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
snprintf((char *)addr, HUGEPAGE_SIZE, "Hello, Huge Pages!");
printf("%s\n", (char *)addr);
if (munmap(addr, HUGEPAGE_SIZE) == -1) {
perror("munmap");
exit(EXIT_FAILURE);
}
return 0;}
Result without fix
==================
# cat /proc/meminfo |grep -i HugePages_Free HugePages_Free: 20 # ./test mmap: Permission denied #
Result with fix
===============
# cat /proc/meminfo |grep -i HugePages_Free HugePages_Free: 20 # ./test Hello, Huge Pages! #
Reported-by Pavithra Prakash <[email protected]>
--- fs/hugetlbfs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/hugetlbfs/inode.c +2 -2
@@ -228,7 +228,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,if (len & ~huge_page_mask (h))return -EINVAL ; -if (len >TASK_SIZE ) +if (len > mmap_end - mmap_min_addr)return -ENOMEM ;if (flags &MAP_FIXED ) {
@@ -240,7 +240,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,if (addr) { addr =ALIGN (addr,huge_page_size (h)); vma =find_vma (mm, addr); -if (mmap_end - len >= addr && +if (mmap_end - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <=vm_start_gap (vma)))return addr; }
Signature · 1 line
2.43.5
Quoted 14 lines · Donet Tom
fs/hugetlbfs/inode.c +1
-1@@ -228,7 +228,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,if (len & ~huge_page_mask (h))return -EINVAL ; -if (len >TASK_SIZE ) +if (len > mmap_end - mmap_min_addr)return -ENOMEM ;if (flags &MAP_FIXED ) {
fs/hugetlbfs/inode.c generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr, · line 246
Quoted 8 lines
fs/hugetlbfs/inode.c +1
-1@@ -240,7 +240,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,if (addr) { addr =ALIGN (addr,huge_page_size (h)); vma =find_vma (mm, addr); -if (mmap_end - len >= addr && +if (mmap_end - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <=vm_start_gap (vma)))return addr; }
There's more difference with generic_get_unmapped_area() than what you are fixing. I think we also need vm_end_gap() here.
Hugetlb code duplication is annoying.
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
Quoted 13 lines · Kirill A . Shutemov
Quoted 12 lines · Donet Tom
fs/hugetlbfs/inode.c +1
-1@@ -228,7 +228,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,if (len & ~huge_page_mask (h))return -EINVAL ; -if (len >TASK_SIZE ) +if (len > mmap_end - mmap_min_addr)return -ENOMEM ;
Quoted 12 lines
fs/hugetlbfs/inode.c generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr, · line 246
Quoted 10 lines
fs/hugetlbfs/inode.c +1
-1if (flags &MAP_FIXED ) {@@ -240,7 +240,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,if (addr) { addr =ALIGN (addr,huge_page_size (h)); vma =find_vma (mm, addr); -if (mmap_end - len >= addr && +if (mmap_end - len >= addr && addr >= mmap_min_addr && (!vma || addr + len <=vm_start_gap (vma)))return addr; }There's more difference with
generic_get_unmapped_area()than what you are fixing. I think we also needvm_end_gap()here.
Thank you for your comment. I will add this change and send V2.
-Donet
Quoted 3 lines
Hugetlb code duplication is annoying.