BPF List
 help / color / mirror / Atom feed
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);
 }
 
 /**

  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