From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: bpf@vger.kernel.org
Cc: Puranjay Mohan <puranjay@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Eduard Zingerman <eddyz87@gmail.com>,
Emil Tsalapatis <emil@etsalapatis.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
Dave Hansen <dave.hansen@linux.intel.com>,
Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
kkd@meta.com, kernel-team@meta.com, x86@kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH bpf-next v1 1/3] x86/mm: Resolve BPF exception fixups for user address faults under SMAP
Date: Fri, 9 Oct 2026 04:49:21 +0200 [thread overview]
Message-ID: <20261009024925.3169077-2-memxor@gmail.com> (raw)
In-Reply-To: <20261009024925.3169077-1-memxor@gmail.com>
With SMAP enabled, do_user_addr_fault() treats a kernel-mode fault on a
user address with EFLAGS.AC clear as a kernel bug: it does not consult the
exception table and oopses right away. That is correct for ordinary kernel
code, where get_kernel_nofault() and the other nofault accessors never let
a user address reach a faulting instruction.
JITed BPF programs are different. A privileged program may dereference a
pointer the verifier cannot prove valid, and the verifier marks such loads
PROBE_MEM. The JIT attaches an exception table entry to each PROBE_MEM
load, so that a fault on an unmapped kernel address zeroes the destination
register and the program continues. Since a user address would oops
instead, the x86 JIT also emits an address range check in front of every
PROBE_MEM load, which keeps user addresses, the guard page above
TASK_SIZE_MAX and the vsyscall page away from the load. The check
duplicates the fault handler's knowledge of the address space layout, got
the vsyscall page wrong until commit b599d7d26d6a ("bpf, x86: Fix PROBE_MEM
runtime load check"), and costs nine instructions and 32 to 39 bytes of
code per load.
When the faulting instruction belongs to a BPF program, resolve its
exception table entry instead of oopsing, exactly as is done for faults on
kernel addresses. The is_bpf_text_address() lookup sits inside the
unlikely() SMAP branch that currently ends in page_fault_oops(), so no path
that does not oops today executes any additional code, and the oops itself
is unchanged when no entry matches. Non-BPF code keeps the existing
behaviour: a kernel-mode user access without STAC still oopses, extable
entry or not.
The next patch uses this to drop the range check from the JIT when SMAP is
enabled. Nothing changes about which addresses a BPF program may read: a
user address never becomes readable, since SMAP forbids the access, and a
PROBE_MEM load of a kernel address is handled as before. Without SMAP the
JIT keeps its range check and this path is never reached.
Acked-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
arch/x86/mm/fault.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index aa88370ce739..2060e5f35d77 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -20,6 +20,7 @@
#include <linux/mm_types.h>
#include <linux/mm.h> /* find_and_lock_vma() */
#include <linux/vmalloc.h>
+#include <linux/filter.h> /* is_bpf_text_address() */
#include <asm/cpufeature.h> /* boot_cpu_has, ... */
#include <asm/traps.h> /* dotraplinkage, ... */
@@ -1262,6 +1263,16 @@ void do_user_addr_fault(struct pt_regs *regs,
if (unlikely(cpu_feature_enabled(X86_FEATURE_SMAP) &&
!(error_code & X86_PF_USER) &&
!(regs->flags & X86_EFLAGS_AC))) {
+ /*
+ * JITed BPF programs dereference untrusted pointers with loads
+ * that carry an exception table entry (PROBE_MEM). SMAP makes
+ * sure such a load cannot read user memory, so resolve the
+ * fault through the exception table, as for an unmapped kernel
+ * address, instead of oopsing.
+ */
+ if (is_bpf_text_address(regs->ip) &&
+ fixup_exception(regs, X86_TRAP_PF, error_code, address))
+ return;
/*
* No extable entry here. This was a kernel access to an
* invalid pointer. get_kernel_nofault() will not get here.
--
2.53.0-Meta
next prev parent reply other threads:[~2026-10-09 2:49 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 2:49 [PATCH bpf-next v1 0/3] bpf, x86: Drop the PROBE_MEM address range check " Kumar Kartikeya Dwivedi
2026-10-09 2:49 ` Kumar Kartikeya Dwivedi [this message]
2026-10-09 4:13 ` [PATCH bpf-next v1 1/3] x86/mm: Resolve BPF exception fixups for user address faults " Borislav Petkov
2026-10-09 15:23 ` Kumar Kartikeya Dwivedi
2026-10-09 2:49 ` [PATCH bpf-next v1 2/3] bpf, x86: Skip the PROBE_MEM address range check " Kumar Kartikeya Dwivedi
2026-10-09 3:42 ` bot+bpf-ci
2026-10-09 2:49 ` [PATCH bpf-next v1 3/3] selftests/bpf: Test PROBE_MEM loads from invalid addresses Kumar Kartikeya Dwivedi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261009024925.3169077-2-memxor@gmail.com \
--to=memxor@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bp@alien8.de \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=dave.hansen@linux.intel.com \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=kernel-team@meta.com \
--cc=kkd@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=puranjay@kernel.org \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®