• Vlastimil Babka's avatar
    x86/mm: fix use-after-free of vma during userfaultfd fault · cb0631fd
    Vlastimil Babka authored
    Syzkaller with KASAN has reported a use-after-free of vma->vm_flags in
    __do_page_fault() with the following reproducer:
    
      mmap(&(0x7f0000000000/0xfff000)=nil, 0xfff000, 0x3, 0x32, 0xffffffffffffffff, 0x0)
      mmap(&(0x7f0000011000/0x3000)=nil, 0x3000, 0x1, 0x32, 0xffffffffffffffff, 0x0)
      r0 = userfaultfd(0x0)
      ioctl$UFFDIO_API(r0, 0xc018aa3f, &(0x7f0000002000-0x18)={0xaa, 0x0, 0x0})
      ioctl$UFFDIO_REGISTER(r0, 0xc020aa00, &(0x7f0000019000)={{&(0x7f0000012000/0x2000)=nil, 0x2000}, 0x1, 0x0})
      r1 = gettid()
      syz_open_dev$evdev(&(0x7f0000013000-0x12)="2f6465762f696e7075742f6576656e742300", 0x0, 0x0)
      tkill(r1, 0x7)
    
    The vma should be pinned by mmap_sem, but handle_userfault() might (in a
    return to userspace scenario) release it and then acquire again, so when
    we return to __do_page_fault() (with other result than VM_FAULT_RETRY),
    the vma might be gone.
    
    Specifically, per Andrea the scenario is
     "A return to userland to repeat the page fault later with a
      VM_FAULT_NOPAGE retval (potentially after handling any pending signal
      during the return to userland). The return to userland is identified
      whenever FAULT_FLAG_USER|FAULT_FLAG_KILLABLE are both set in
      vmf->flags"
    
    However, since commit a3c4fb7c ("x86/mm: Fix fault error path using
    unsafe vma pointer") there is a vma_pkey() read of vma->vm_flags after
    that point, which can thus become use-after-free.  Fix this by moving
    the read before calling handle_mm_fault().
    Reported-by: default avatarsyzbot <bot+6a5269ce759a7bb12754ed9622076dc93f65a1f6@syzkaller.appspotmail.com>
    Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
    Suggested-by: default avatarKirill A. Shutemov <kirill@shutemov.name>
    Fixes: 3c4fb7c9c2e ("x86/mm: Fix fault error path using unsafe vma pointer")
    Reviewed-by: default avatarAndrea Arcangeli <aarcange@redhat.com>
    Signed-off-by: default avatarVlastimil Babka <vbabka@suse.cz>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    cb0631fd
Name
Last commit
Last update
..
alpha Loading commit data...
arc Loading commit data...
arm Loading commit data...
arm64 Loading commit data...
blackfin Loading commit data...
c6x Loading commit data...
cris Loading commit data...
frv Loading commit data...
h8300 Loading commit data...
hexagon Loading commit data...
ia64 Loading commit data...
m32r Loading commit data...
m68k Loading commit data...
metag Loading commit data...
microblaze Loading commit data...
mips Loading commit data...
mn10300 Loading commit data...
nios2 Loading commit data...
openrisc Loading commit data...
parisc Loading commit data...
powerpc Loading commit data...
s390 Loading commit data...
score Loading commit data...
sh Loading commit data...
sparc Loading commit data...
tile Loading commit data...
um Loading commit data...
unicore32 Loading commit data...
x86 Loading commit data...
xtensa Loading commit data...
.gitignore Loading commit data...
Kconfig Loading commit data...