Skip to content

Commit 230c92a

Browse files
aagittorvalds
authored andcommitted
userfaultfd: propagate the full address in THP faults
The THP faults were not propagating the original fault address. The latest version of the API with uffd.arg.pagefault.address is supposed to propagate the full address through THP faults. This was not a kernel crashing bug and it wouldn't risk to corrupt user memory, but it would cause a SIGBUS failure because the wrong page was being copied. For various reasons this wasn't easily reproducible in the qemu workload, but the strestest exposed the problem immediately. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent dfa37dc commit 230c92a

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

mm/huge_memory.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -717,13 +717,14 @@ static inline pmd_t mk_huge_pmd(struct page *page, pgprot_t prot)
717717

718718
static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
719719
struct vm_area_struct *vma,
720-
unsigned long haddr, pmd_t *pmd,
720+
unsigned long address, pmd_t *pmd,
721721
struct page *page, gfp_t gfp,
722722
unsigned int flags)
723723
{
724724
struct mem_cgroup *memcg;
725725
pgtable_t pgtable;
726726
spinlock_t *ptl;
727+
unsigned long haddr = address & HPAGE_PMD_MASK;
727728

728729
VM_BUG_ON_PAGE(!PageCompound(page), page);
729730

@@ -765,7 +766,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
765766
mem_cgroup_cancel_charge(page, memcg);
766767
put_page(page);
767768
pte_free(mm, pgtable);
768-
ret = handle_userfault(vma, haddr, flags,
769+
ret = handle_userfault(vma, address, flags,
769770
VM_UFFD_MISSING);
770771
VM_BUG_ON(ret & VM_FAULT_FALLBACK);
771772
return ret;
@@ -841,7 +842,7 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
841842
if (pmd_none(*pmd)) {
842843
if (userfaultfd_missing(vma)) {
843844
spin_unlock(ptl);
844-
ret = handle_userfault(vma, haddr, flags,
845+
ret = handle_userfault(vma, address, flags,
845846
VM_UFFD_MISSING);
846847
VM_BUG_ON(ret & VM_FAULT_FALLBACK);
847848
} else {
@@ -865,7 +866,8 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
865866
count_vm_event(THP_FAULT_FALLBACK);
866867
return VM_FAULT_FALLBACK;
867868
}
868-
return __do_huge_pmd_anonymous_page(mm, vma, haddr, pmd, page, gfp, flags);
869+
return __do_huge_pmd_anonymous_page(mm, vma, address, pmd, page, gfp,
870+
flags);
869871
}
870872

871873
int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,

0 commit comments

Comments
 (0)