From: Jiri Olsa <olsajiri@gmail.com>
To: bot+bpf-ci@kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, bpf@vger.kernel.org,
linux-mm@kvack.org, andrii@kernel.org, eddyz87@gmail.com,
memxor@gmail.com, ljs@kernel.org, john.fastabend@gmail.com,
nierro92@gmail.com, martin.lau@kernel.org,
yonghong.song@linux.dev, mason@kernel.org,
ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next 2/8] bpf: Add user memory kfuncs
Date: Fri, 30 Oct 2026 14:08:16 +0100 [thread overview]
Message-ID: <auSWwHhZwhUbSVf1@krava> (raw)
In-Reply-To: <571f32a410a85199bc9bcecfe07a9a9b6ef425b2052643e64031dd246c13691e@mail.kernel.org>
On Thu, Oct 29, 2026 at 10:12:12PM +0000, bot+bpf-ci@kernel.org wrote:
SNIP
> > +__bpf_kfunc unsigned long bpf_user_mmap(unsigned long len, unsigned long prot)
> > +{
> > + if (!bpf_user_mm_ok())
> > + return -EPERM;
> > + return vm_mmap(NULL, 0, len, prot, MAP_PRIVATE | MAP_ANONYMOUS, 0);
> > +}
>
> Can this vm_mmap() call fail for ia32 tasks, and for 64-bit tasks when
> CONFIG_X86_X32_ABI=y, because it is not made from a syscall?
>
> On x86_64 the address picked by vm_mmap() depends on the bitness of the
> current syscall:
>
> vm_mmap()
> do_mmap()
> __get_unmapped_area()
> arch_get_unmapped_area_topdown()
> info.high_limit = get_mmap_base(0);
>
> arch/x86/mm/mmap.c:get_mmap_base() {
> if (in_32bit_syscall()) {
> return is_legacy ? mm->mmap_compat_legacy_base
> : mm->mmap_compat_base;
> }
> return is_legacy ? mm->mmap_legacy_base : mm->mmap_base;
> }
>
> The sleepable kprobe programs that can call this kfunc run either from
> uprobe_notify_resume() -> handle_swbp() -> handler_chain() (or
> uprobe_prog_run()) on the int3 return-to-user path, or from bpf_task_work
> callbacks run by task_work_run(). TS_COMPAT is set only in
> syscall_32_enter() and is cleared on every return to user mode, so it is
> clear in all of these paths.
>
> For an ia32 task (TIF_ADDR32) on a kernel without CONFIG_X86_X32_ABI, the
> top-down search therefore runs below the 64-bit mm->mmap_base. Everything
> above 4GB is free in such a task, so the search returns an address above 4GB
> and __get_unmapped_area() rejects it:
>
> if (addr > TASK_SIZE - len)
> return -ENOMEM;
>
> The bottom-up legacy layout fails the same way, because find_start_end() also
> starts from get_mmap_base(1). So the kfunc always returns -ENOMEM for ia32
> processes.
>
> With CONFIG_X86_X32_ABI=y the result is the opposite. Exception entry
> stores orig_ax = -1, so in_x32_syscall() is true in the uprobe handler and
> 64-bit processes get the compat (below 4GB) layout. A large len then fails
> with -ENOMEM in the bottom-up fallback (end = task_size_32bit()) even though
> 64-bit address space is free.
>
> The kernel documents this dependency in __set_personality_x32(): "The x86
> mmap() code relies on the syscall bitness so set x32 syscall bit right here
> to make in_32bit_syscall() work during exec()". The uprobes XOL area avoids
> the problem by passing an explicit TASK_SIZE - PAGE_SIZE hint.
>
> Neither the kernel-doc ("into the current process") nor the commit message
> mentions this limitation, and the selftests later in the series only exercise
> 64-bit binaries. Should this limitation be handled or documented?
that might be a problem.. we could use similar workaround that's
used in arch_uprobe_get_xol_area and set TS_COMPAT before we call
vm_mmap and restore after (like below)
or we can always bail out for compat apps
jirka
---
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 4ca2ac8d372d..c9dbd38ca125 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -32,6 +32,9 @@
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/limits.h>
+#ifdef CONFIG_X86_64
+#include <asm/thread_info.h>
+#endif
#include "../../lib/kstrtox.h"
@@ -3781,6 +3784,27 @@ static bool bpf_user_mm_ok(void)
return current->mm && !(current->flags & (PF_KTHREAD | PF_EXITING));
}
+#ifdef CONFIG_X86_64
+static unsigned long bpf_user_vm_mmap(unsigned long len, unsigned long prot)
+{
+ struct thread_info *ti = current_thread_info();
+ bool compat = test_thread_flag(TIF_ADDR32);
+ unsigned long addr;
+
+ if (compat)
+ ti->status |= TS_COMPAT;
+ addr = vm_mmap(NULL, 0, len, prot, MAP_PRIVATE | MAP_ANONYMOUS, 0);
+ if (compat)
+ ti->status &= ~TS_COMPAT;
+ return addr;
+}
+#else
+static unsigned long bpf_user_vm_mmap(unsigned long len, unsigned long prot)
+{
+ return vm_mmap(NULL, 0, len, prot, MAP_PRIVATE | MAP_ANONYMOUS, 0);
+}
+#endif
+
/**
* bpf_user_mmap() - Map private anonymous memory into the current process
* @len: Length of the mapping
@@ -3797,7 +3821,7 @@ __bpf_kfunc unsigned long bpf_user_mmap(unsigned long len, unsigned long prot)
{
if (!bpf_user_mm_ok())
return -EPERM;
- return vm_mmap(NULL, 0, len, prot, MAP_PRIVATE | MAP_ANONYMOUS, 0);
+ return bpf_user_vm_mmap(len, prot);
}
/**
next prev parent reply other threads:[~2026-10-30 13:08 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 21:25 [PATCH bpf-next 0/8] bpf: Add user memory kfuncs Jiri Olsa
2026-10-29 21:25 ` [PATCH bpf-next 1/8] bpf: Add __srcptr kfunc argument suffix Jiri Olsa
2026-10-29 21:49 ` Andrii Nakryiko
2026-10-30 10:50 ` Jiri Olsa
2026-10-30 16:26 ` Alexei Starovoitov
2026-10-29 21:25 ` [PATCH bpf-next 2/8] bpf: Add user memory kfuncs Jiri Olsa
2026-10-29 22:00 ` Andrii Nakryiko
2026-10-30 11:08 ` Jiri Olsa
2026-10-29 22:12 ` bot+bpf-ci
2026-10-30 13:07 ` Jiri Olsa
2026-10-30 13:08 ` Jiri Olsa [this message]
2026-10-29 21:25 ` [PATCH bpf-next 3/8] selftests/bpf: Add get_procmap_info helper Jiri Olsa
2026-10-29 21:25 ` [PATCH bpf-next 4/8] selftests/bpf: Test __srcptr kfunc arguments Jiri Olsa
2026-10-29 21:25 ` [PATCH bpf-next 5/8] selftests/bpf: Test user memory mmap kfuncs Jiri Olsa
2026-10-29 21:59 ` bot+bpf-ci
2026-10-30 13:08 ` Jiri Olsa
2026-10-29 21:25 ` [PATCH bpf-next 6/8] selftests/bpf: Test user memory page exec Jiri Olsa
2026-10-29 21:25 ` [PATCH bpf-next 7/8] selftests/bpf: Test bpf_copy_to_user kfunc Jiri Olsa
2026-10-29 21:25 ` [PATCH bpf-next 8/8] selftests/bpf: Test user memory kfunc errors Jiri Olsa
2026-10-29 21:59 ` bot+bpf-ci
2026-10-30 13:08 ` Jiri Olsa
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=auSWwHhZwhUbSVf1@krava \
--to=olsajiri@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bot+bpf-ci@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=martin.lau@kernel.org \
--cc=mason@kernel.org \
--cc=memxor@gmail.com \
--cc=nierro92@gmail.com \
--cc=yonghong.song@linux.dev \
/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