mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] uaccess: Refuse and warn on user accesses when current->mm is NULL
@ 2026-10-26 21:52 James Houghton
  2026-10-26 21:52 ` [RFC PATCH 01/10] scsi: bsg: Don't copy sense data to user memory when canceled James Houghton
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: James Houghton @ 2026-10-26 21:52 UTC (permalink / raw)
  To: Andrew Morton, Alexander Viro
  Cc: Thomas Gleixner, Peter Zijlstra, Kees Cook, Arnd Bergmann,
	David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Sean Christopherson, Paolo Bonzini, Jim Mattson, Jens Axboe,
	Pavel Begunkov, James E.J. Bottomley, Martin K. Petersen,
	David Sterba, Chris Mason, Alexei Starovoitov, Daniel Borkmann,
	John Fastabend, Josh Poimboeuf, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, linux-mm, linux-fsdevel, kvm, io-uring, linux-scsi,
	linux-btrfs, bpf, linux-trace-kernel, linux-perf-users,
	linux-kernel, James Houghton

Hi everyone,

This series comes out of a set of bugs that were found in KVM where the
kernel can sometimes write to a random process's user memory[1]. The KVM
fixes at [1] are still required, even with this uaccess series, as noted
by Sean here[2] and below in this cover letter. The beginning of this
series includes fixes for similar bugs found through static analysis
with Claude Opus 5.5. I don't think any of these bugs are more severe
than the KVM bugs[1].

We hit one of the KVM bugs in production, and it was challenging to
debug. This series makes such bugs, where the kernel is doing uaccess
without an mm, much more obvious.

The Cc list is wide because the fixes at the start of the series touch
several subsystems: SCSI (patch 1), btrfs (patch 2), BPF (patch 3),
tracing (patch 4) and perf (patch 5). They're included because the new
warning in patches 6-10 would otherwise fire on those paths. The core
uaccess change is in patches 6-10.

I have a reproducer only for patch 3 (a bpf_wq callback calling
bpf_copy_from_user(), which triggers the new WARN without the patch and
fails with -EFAULT with it); some details are in the notes section of
patch 3.

Patches 1, 2, 4 and 5 are only build-tested (plus syzkaller running on
the final kernel). Let me know if you'd like to see reproducers (or if
any of the patches are incorrect and should be dropped).

== Introduction ==

Accessing user memory from a task that has no mm is always a bug. This
can happen from a kernel thread that is not using kthread_use_mm(), or
from a task that has already gone through exit_mm(), e.g. when the last
reference to a file is dropped at exit and its release handler runs
from exit_task_work(). For example, KVM's nVMX code can write to guest
memory while a vCPU is being freed during VM destruction[1], and other
drivers may have similar bugs.

Such an access does not reliably fail. The user portion of the address
space belongs to whatever mm happens to be lazily loaded, if any. If
the access faults, the fault handler refuses to handle it and the copy
fails, but if the page is already mapped, the access silently reads or
writes another task's memory.

== Fixes ==

Patches 1-5 fix existing places that access current's user memory
without an mm:

 - Patches 1 and 2 fix io_uring passthrough completions in scsi_bsg and
   btrfs that copy to the submitter's user memory even when io_uring
   runs them canceled from a kworker, e.g. after the submitter exited.
   These are real bugs of the kind this series is meant to catch.

 - Patch 3 makes the sleepable BPF user copy helpers fail when
   current->mm is NULL, e.g. for bpf_wq callbacks or lsm.s programs
   running from kernel threads or exiting tasks.

 - Patches 4 and 5 make stack_trace_save_user() (ftrace's
   userstacktrace option) and get_perf_callchain() (bpf_get_task_stack()
   on the current task) use is_user_task(), so that they don't unwind
   the user stack of PID 1 before exec, usermode helpers before exec,
   or tasks that have gone through exit_mm().

== The New WARN ==

The rest of the series makes the generic uaccess helpers WARN_ON_ONCE()
and refuse the access when current->mm is NULL:

 - Patch 6 adds uaccess_should_fail(), which combines the existing
   should_fail_usercopy() fault injection check with the NULL mm check,
   and uses it in place of should_fail_usercopy(). This covers
   copy_{to,from}_user() on all architectures (including the masked
   user access paths, which never call access_ok()), the
   __copy_{to,from}_user() variants used by KVM's guest memory
   accessors, the user-backed iov_iter copy routines and
   strncpy_from_user().

 - Patch 7 makes the user nofault helpers fail quietly when
   current->mm is NULL. They are meant to be callable from any context
   (BPF, kprobes, perf), including from kernel threads, where failing
   is the expected outcome rather than a bug.

 - Patch 8 splits the NULL mm check out into uaccess_without_mm() and
   adds it to __copy_from_user_inatomic(), without also enabling fault
   injection there.

 - Patch 9 adds the check to the remaining generic paths: the scoped
   user access helpers, strnlen_user(), check_zeroed_user(), and the
   iov_iter routines that call into architecture-specific helpers.

 - Patch 10 is included for reference only. It moves the warning out of
   line, which removes ~16 KB of __bug_table growth on arm64 (where
   copy_{to,from}_user() are inlined), at the cost of warning only once
   system-wide and a slight size regression on x86_64. With defconfig +
   KVM, patches 6-9 grow vmlinux by +5,884 B (+0.014%) on x86_64 and
   +40,948 B (+0.10%) on arm64 without it, and by +9,714 B (+0.023%)
   and +24,609 B (+0.06%) with it.

The checks are deliberately limited to generic code. Accesses
implemented entirely by architectures (get_user(), put_user(),
clear_user(), and direct users of user_access_begin() or
masked_user_access_begin()) are not covered. Please let me know if the
new check should be placed elsewhere.

The check also cannot catch a valid mm that isn't the one the caller
expects, e.g. when a file's release or ioctl handlers run in a
different process than the one that created it. Code that keeps user
addresses belonging to a specific mm still has to compare current->mm
against that mm itself. For KVM, Sean's series[1] does exactly that for
guest memory accesses, and so complements this one: it handles the case
where the VM is destroyed from another process, which this series cannot
detect.

Without [1], the nVMX vCPU teardown path described there may trigger
the new warning when the last reference to a VM is dropped by an
exiting task or by the delayed fput kworker. The write to guest memory
is then refused, which is also what [1] does.

For example, running Jim Mattson's selftest for that bug[3] (adapted
slightly) on a kernel with this series but without [1] gives the
following warning, and the write to guest memory is refused. The warning
comes from uaccess_warn_without_mm() because patch 10 was applied;
without it, it points at the inlined copy helper in the caller instead.

  WARNING: lib/usercopy.c:31 at uaccess_warn_without_mm+0xa/0x12, CPU#2: vmx_shadow_vmcs/5299
  Call Trace:
   kvm_write_guest_offset_cached.cold+0xa/0xf
   __nested_vmx_vmexit+0x1974/0x3fd0
   nested_vmx_free_vcpu+0xb3/0xd0
   vmx_vcpu_free+0x96/0x350
   kvm_arch_vcpu_destroy+0x15c/0x400
   kvm_destroy_vcpus+0x270/0x3f0
   kvm_arch_destroy_vm+0xc7/0x230
   kvm_put_kvm+0x560/0xbf0
   kvm_vm_release+0x3c/0x50
   __fput+0x3f8/0xb50
   fput_close_sync+0x113/0x250
   filp_close_sync+0x75/0xa0
   put_files_struct+0x201/0x390
   exit_files+0x97/0xd0
   do_exit+0x872/0x2a00
   do_group_exit+0xd5/0x2a0
   __x64_sys_exit_group+0x3c/0x50

== Testing ==

Build-tested on x86_64 and arm64. Verified that the KVM reproducer hits
the new WARN, and that the BPF reproducer hits it without patch 3.

I'm also fuzzing this series with syzkaller on x86_64 (syzbot's
upstream KASAN config, nested VMX enabled), so far for about a day and
a half. syzkaller hasn't triggered the new warning yet, i.e. it hasn't
found any other path that accesses user memory without an mm. Fuzzing
is ongoing, and I'll report anything it finds in reply to this RFC.

Please let me know what you think. Thank you!

[1] https://lore.kernel.org/kvm/20261001202234.3794060-1-seanjc@google.com
[2] https://lore.kernel.org/kvm/aqMBidJ_96qroogH@google.com/
[3] https://lore.kernel.org/kvm/20260911191011.528460-1-jmattson@google.com/

James Houghton (10):
  scsi: bsg: Don't copy sense data to user memory when canceled
  btrfs: Don't copy encoded read data to user memory when canceled
  bpf: Fail sleepable user copy helpers when current->mm is NULL
  stacktrace: Don't unwind the user stack without an mm
  perf/core: Don't unwind the user stack without an mm
  uaccess: Refuse and warn on user copies when current->mm is NULL
  uaccess: Fail user nofault helpers quietly when current->mm is NULL
  uaccess: Refuse and warn on __copy_from_user_inatomic() without an mm
  uaccess: Refuse and warn on more user accesses without an mm
  uaccess: Move the NULL mm warning out of line

 drivers/scsi/scsi_bsg.c   | 10 +++++++-
 fs/btrfs/ioctl.c          | 10 ++++++++
 include/linux/uaccess.h   | 50 +++++++++++++++++++++++++++++++++++----
 kernel/bpf/helpers.c      | 11 +++++++--
 kernel/events/callchain.c | 12 ++++++----
 kernel/stacktrace.c       |  8 +++++--
 kernel/trace/bpf_trace.c  |  4 ++++
 lib/iov_iter.c            | 12 ++++++++--
 lib/strncpy_from_user.c   |  2 +-
 lib/strnlen_user.c        |  3 +++
 lib/usercopy.c            |  9 +++++++
 mm/maccess.c              | 17 +++++++++++++
 12 files changed, 131 insertions(+), 17 deletions(-)


base-commit: 2a08195e4db5aba84600db6518089a1dbe2d04c7
-- 
2.56.0.307.g5fe7bd680c-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2026-10-27  2:42 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26 21:52 [RFC PATCH 00/10] uaccess: Refuse and warn on user accesses when current->mm is NULL James Houghton
2026-10-26 21:52 ` [RFC PATCH 01/10] scsi: bsg: Don't copy sense data to user memory when canceled James Houghton
2026-10-27  2:41   ` Jens Axboe
2026-10-26 21:52 ` [RFC PATCH 02/10] btrfs: Don't copy encoded read " James Houghton
2026-10-27  2:42   ` Jens Axboe
2026-10-26 21:52 ` [RFC PATCH 03/10] bpf: Fail sleepable user copy helpers when current->mm is NULL James Houghton
2026-10-26 22:30   ` bot+bpf-ci
2026-10-26 21:52 ` [RFC PATCH 04/10] stacktrace: Don't unwind the user stack without an mm James Houghton
2026-10-26 22:30   ` bot+bpf-ci
2026-10-26 22:55     ` James Houghton
2026-10-26 21:52 ` [RFC PATCH 05/10] perf/core: " James Houghton
2026-10-26 21:52 ` [RFC PATCH 06/10] uaccess: Refuse and warn on user copies when current->mm is NULL James Houghton
2026-10-26 22:42   ` bot+bpf-ci
2026-10-26 23:41     ` James Houghton
2026-10-26 21:52 ` [RFC PATCH 07/10] uaccess: Fail user nofault helpers quietly " James Houghton
2026-10-26 21:52 ` [RFC PATCH 08/10] uaccess: Refuse and warn on __copy_from_user_inatomic() without an mm James Houghton
2026-10-26 22:30   ` bot+bpf-ci
2026-10-26 22:41     ` James Houghton
2026-10-26 21:52 ` [RFC PATCH 09/10] uaccess: Refuse and warn on more user accesses " James Houghton
2026-10-26 21:52 ` [RFC PATCH 10/10] uaccess: Move the NULL mm warning out of line James Houghton
2026-10-26 23:02   ` Arnd Bergmann
2026-10-26 23:51     ` James Houghton
2026-10-27  0:12 ` [RFC PATCH 00/10] uaccess: Refuse and warn on user accesses when current->mm is NULL Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®