Re: [linus:master] [gup] a425ac5365: WARNING:at_mm/gup.c:#__get_user_pages

From: John Hubbard
Date: Wed Jul 05 2023 - 03:27:27 EST


On 7/4/23 07:12, Linus Torvalds wrote:
...
> And I *do* want the backtrace from the warning (in this case, it shows
> that it's the "process_vm_readv/writev()" path, which actually might
> be worth adding stack expansion to, the same way __access_remote_vm()
> does).

This is good timing, because I was looking for an email to reply to, to
report that I've isolated a somewhat more valid user space behavior that
is triggering this, via __access_remote_vm().

It happens on my main workstation when there is a problem with any app
that uses Chromium's crashpad [1] to report problems. crashpad is a
rather sophisticated app that does extensive forensics, including a
bunch of pread64() system calls of /proc/pid/mem. Fortunately, the unit
test suite included with [1] also reproduces the problem very reliably.

So it boils down to this: crashpad is reading from a valid starting
address, inside the vma for the ld-linux-x86-64.so.2 file, but it reads
a full 4KB page's worth, which takes it past the end of that vma.

And although the expand_stack() logic is there as part of the
__access_remote_vm() path, that logic ignores the size of the read! So
it slips past without trying to expand the stack.

Note that while next vma is indeed the stack, it is 919 GB away--a very
large gap.

The crashpad app is arguably a little bit buggy. It is reading a bit
more than it should, and landing in between vmas for the tail end of the
read. However, the app seems to handle it OK.

/proc/pid/maps:
7f19d671a000-7f19d671c000 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7fffc2c28000-7fffc2c4a000 [stack] (919 GB above previous vma)

"start" address in __get_user_pages(): 0x7f19d671c000

dump_vma() if the WARN_ON_ONCE() fires:
vma ffff8881143e0e60 start 00007fffc2c28000 end 00007fffc2c4a000 mm ffff888106adbd40
prot 8000000000000025 anon_vma ffff88810b0735f0 vm_ops 0000000000000000
pgoff 7ffffffdd file 0000000000000000 private_data 0000000000000000
flags: 0x100173(read|write|mayread|maywrite|mayexec|growsdown|account)

Analysis of the ranges, which overlap:
0x7f19d671a000 start of /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7f19d671b8a0 pread64 start (read size: 4096)
0x7f19d671c000 end of /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
0x7f19d671c8a0 pread64 end

WARNING: CPU: 11 PID: 8490 at mm/gup.c:1180 __get_user_pages+0x53e/0x670
...
Call Trace:
<TASK>
? __warn+0xc5/0x1f0
? __get_user_pages+0x53e/0x670
? report_bug+0xcd/0x160
? handle_bug+0x3d/0x80
? exc_invalid_op+0x16/0x50
? asm_exc_invalid_op+0x16/0x20
? __get_user_pages+0x53e/0x670
get_user_pages_remote+0x17f/0x490
__access_remote_vm+0x106/0x2c0
mem_rw+0x134/0x1e0
vfs_read+0xdf/0x2d0
? __pfx_rcu_lock_release+0x10/0x10
? __fget_files+0x128/0x140
__x64_sys_pread64+0x6b/0xc0
do_syscall_64+0x41/0x90
entry_SYSCALL_64_after_hwframe+0x6e/0xd8

[1] https://chromium.googlesource.com/crashpad/crashpad.git

thanks,
--
John Hubbard
NVIDIA