When obtaining resv_map from vma, it is necessary to simultaneously determine the flag HPAGE_RESV_OWNER of vm_private_data. Only when they are met simultaneously, resv_map is valid. Reported-and-tested-by: syzbot+6ada951e7c0f7bc8a71e@xxxxxxxxxxxxxxxxxxxxxxxxx Fixes: bf4916922c60 ("hugetlbfs: extend hugetlb_vma_lock to private VMAs") Signed-off-by: Edward Adam Davis <eadavis@xxxxxx> --- include/linux/hugetlb.h | 5 ++++- mm/hugetlb.c | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 47d25a5e1933..14babc602f14 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -179,6 +179,7 @@ struct address_space *hugetlb_page_mapping_lock_write(struct page *hpage); extern int sysctl_hugetlb_shm_group; extern struct list_head huge_boot_pages; +static int is_vma_resv_set(struct vm_area_struct *vma, unsigned long flag); /* arch callbacks */ @@ -1265,9 +1266,11 @@ static inline bool __vma_shareable_lock(struct vm_area_struct *vma) return (vma->vm_flags & VM_MAYSHARE) && vma->vm_private_data; } +#define HPAGE_RESV_OWNER (1UL << 0) static inline bool __vma_private_lock(struct vm_area_struct *vma) { - return (!(vma->vm_flags & VM_MAYSHARE)) && vma->vm_private_data; + return (!(vma->vm_flags & VM_MAYSHARE)) && vma->vm_private_data && + is_vma_resv_set(vma, HPAGE_RESV_OWNER); } /* diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 1301ba7b2c9a..97ea782dfba6 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1033,7 +1033,6 @@ __weak unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) * bits of the reservation map pointer, which are always clear due to * alignment. */ -#define HPAGE_RESV_OWNER (1UL << 0) #define HPAGE_RESV_UNMAPPED (1UL << 1) #define HPAGE_RESV_MASK (HPAGE_RESV_OWNER | HPAGE_RESV_UNMAPPED) -- 2.25.1