From: sashiko-bot@kernel.org
To: "Jiri Olsa" <jolsa@kernel.org>,
"Alexei Starovoitov" <ast@kernel.org>,
"Daniel Borkmann" <daniel@iogearbox.net>
Cc: bpf@vger.kernel.org, "Andrii Nakryiko" <andrii@kernel.org>,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
linux-mm@kvack.org, "Andrew Morton" <akpm@linux-foundation.org>,
"Liam R. Howlett" <liam@infradead.org>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Shuah Khan" <shuah@kernel.org>,
"John Fastabend" <john.fastabend@gmail.com>
Subject: Re: [RFC bpf-next 2/9] bpf: Add uprobe faultable user copy kfunc
Date: Wed, 21 Oct 2026 20:22:24 +0000 [thread overview]
Message-ID: <sashiko-outbox-180638@kernel.org> (raw)
In-Reply-To: <20261021195759.119421-3-jolsa@kernel.org>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] bpf: missing CAP_SYS_ADMIN check in user_mem_kfunc_filter()
- [High] bpf: hardened usercopy BUG() in bpf_probe_write_user_faultable()
- [Medium] bpf: missing prog->sleepable check in user_mem_kfunc_filter()
- [Low] bpf: unused enum user_mem_kfunc_id in kernel/bpf/helpers.c
--
commit bbd6dece6abea0ce7dfa98ce448c7aae57de64d1
Author: Jiri Olsa <jolsa@kernel.org>
bpf: Add uprobe faultable user copy kfunc
This patch adds the bpf_probe_write_user_faultable() sleepable kfunc to copy
data to user memory with page faults enabled. It registers the kfunc for
BPF_PROG_TYPE_KPROBE programs and filters access with
LOCKDOWN_BPF_WRITE_USER.
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 648abe1ba63ae..4d9e9423826a9 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
[ ... ]
> @@ -3738,6 +3739,36 @@ __bpf_kfunc int bpf_copy_from_user_mm(void *dst, u32 dst__sz,
> return ret;
> }
>
> +/**
> + * bpf_probe_write_user_faultable() - Copy data to userspace with page faults
> + * enabled
> + * @unsafe_dst__ign: Destination address in the current task's address space.
> + * @src__srcptr: Source buffer in BPF-accessible memory.
> + * @src__sz: Number of bytes to copy.
> + *
> + * Copies data to userspace, allowing page faults to resolve the destination
> + * mapping. A failed copy may have written a prefix of the source buffer.
> + *
> + * Return: 0 on success, -EFAULT if the copy is incomplete, or -EPERM if the
> + * current task cannot safely access userspace.
> + */
> +__bpf_kfunc int bpf_probe_write_user_faultable(void __user *unsafe_dst__ign,
> + const void *src__srcptr,
> + u32 src__sz)
> +{
> + if (unlikely(in_interrupt() ||
> + current->flags & (PF_KTHREAD | PF_EXITING)))
> + return -EPERM;
> + if (unlikely(!nmi_uaccess_okay()))
> + return -EPERM;
> + if (unlikely(!current->mm))
> + return -EFAULT;
> + if (copy_to_user(unsafe_dst__ign, src__srcptr, src__sz))
> + return -EFAULT;
[Severity: High]
Can calling copy_to_user() directly on src__srcptr trigger a hardened
usercopy bug when a BPF program passes a trusted BTF object pointer?
In kernel/bpf/verifier.c, get_kfunc_arg_type() classifies src__srcptr paired
with src__sz as ARG_PTR_TO_MEM | MEM_RDONLY. During verification,
check_reg_type() permits mem_types, which includes:
kernel/bpf/verifier.c:
PTR_TO_BTF_ID | PTR_TRUSTED,
and check_helper_mem_access() allows BPF_READ access on scalar fields of
trusted BTF objects (such as &task->pid or task->comm from
bpf_get_current_task_btf()).
At runtime, copy_to_user() calls check_copy_size(src__srcptr, src__sz, true)
-> __check_object_size() -> __check_heap_object() in mm/slub.c:
mm/slub.c:__check_heap_object() {
...
usercopy_abort("SLUB object", s->name, to_user, offset, n);
}
When src__srcptr points to a field in a dedicated slab cache outside its
whitelisted usercopy region (for example task_struct_cachep, mm_cachep,
files_cachep, or fs_cachep), wouldn't __check_heap_object() call
usercopy_abort() and panic the kernel when CONFIG_HARDENED_USERCOPY is
enabled?
> +
> + return 0;
> +}
> +
> /**
> * bpf_copy_from_user_mm_str() - Copy a string from an address space
> * @dst: Destination address, in kernel space. This buffer must be
> @@ -5139,6 +5170,31 @@ static const struct btf_kfunc_id_set generic_kfunc_set = {
> .set = &generic_btf_ids,
> };
>
> +BTF_KFUNCS_START(user_mem_btf_ids)
> +BTF_ID_FLAGS(func, bpf_probe_write_user_faultable, KF_SLEEPABLE | KF_PERFMON)
> +BTF_KFUNCS_END(user_mem_btf_ids)
> +
> +enum user_mem_kfunc_id {
> + KF_bpf_probe_write_user_faultable,
> +};
[Severity: Low]
Is enum user_mem_kfunc_id left over from an earlier version of the patch?
Since user_mem_kfunc_filter() compares kfunc_id against
bpf_probe_write_user_faultable_btf_id[0], neither enum user_mem_kfunc_id nor
KF_bpf_probe_write_user_faultable is used anywhere in kernel/bpf/helpers.c.
> +
> +BTF_ID_LIST_SINGLE(bpf_probe_write_user_faultable_btf_id, func,
> + bpf_probe_write_user_faultable)
> +
> +static int user_mem_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id)
> +{
> + if (kfunc_id == bpf_probe_write_user_faultable_btf_id[0])
> + return security_locked_down(LOCKDOWN_BPF_WRITE_USER);
[Severity: Critical]
Should user_mem_kfunc_filter() also verify that the program has
CAP_SYS_ADMIN via bpf_token_capable(prog->aux->token, CAP_SYS_ADMIN)?
In user_mem_btf_ids, bpf_probe_write_user_faultable is marked with
KF_PERFMON, which in check_kfunc_call() in kernel/bpf/verifier.c only checks
env->allow_ptr_leaks (satisfied by CAP_PERFMON). Meanwhile, for the existing
bpf_probe_write_user() helper, bpf_tracing_func_proto() in
kernel/trace/bpf_trace.c enforces CAP_SYS_ADMIN in addition to lockdown:
kernel/trace/bpf_trace.c:bpf_tracing_func_proto() {
...
if (!bpf_token_capable(prog->aux->token, CAP_SYS_ADMIN))
return NULL;
switch (func_id) {
case BPF_FUNC_probe_write_user:
return security_locked_down(LOCKDOWN_BPF_WRITE_USER) < 0 ?
NULL : &bpf_probe_write_user_proto;
...
}
And include/uapi/linux/capability.h documents this boundary under CAP_BPF:
* CAP_SYS_ADMIN is required to use bpf_probe_write_user.
Without a bpf_token_capable(prog->aux->token, CAP_SYS_ADMIN) check in
user_mem_kfunc_filter(), couldn't a process or container granted only
CAP_BPF and CAP_PERFMON attach a sleepable uprobe or uprobe_multi program to
a shared library and overwrite memory in privileged processes?
> +
> + return 0;
> +}
[Severity: Medium]
Does user_mem_kfunc_filter() also need to check prog->sleepable to restrict
bpf_probe_write_user_faultable() to sleepable uprobes as described in the
commit message?
Because BPF_PROG_TYPE_KPROBE is shared by kernel kprobes and uprobes, the
uprobe-only restriction for sleepable programs is enforced at attach time by
checking prog->sleepable in __perf_event_set_bpf_prog() and
bpf_kprobe_multi_link_attach().
In check_kfunc_call() in kernel/bpf/verifier.c, KF_SLEEPABLE checks
in_sleepable_context(env) rather than prog->sleepable. When a non-sleepable
BPF_PROG_TYPE_KPROBE program (prog->sleepable == false) registers a callback
via bpf_task_work_schedule_signal(), bpf_task_work_schedule_resume(), or
bpf_wq_set_callback(), push_callback_call() marks the callback state as
sleepable via is_async_cb_sleepable():
kernel/bpf/verifier.c:is_async_cb_sleepable() {
/* bpf_wq and bpf_task_work callbacks are always sleepable. */
if (bpf_pseudo_kfunc_call(insn) && insn->off == 0 &&
(is_bpf_wq_set_callback_kfunc(insn->imm) || is_task_work_add_kfunc(insn->imm)))
return true;
return false;
}
Without checking !prog->sleepable in user_mem_kfunc_filter(), wouldn't a
non-sleepable kernel kprobe, kretprobe, or kprobe_multi program be able to
call bpf_probe_write_user_faultable() from a bpf_task_work callback?
> +
> +static const struct btf_kfunc_id_set user_mem_kfunc_set = {
> + .owner = THIS_MODULE,
> + .set = &user_mem_btf_ids,
> + .filter = user_mem_kfunc_filter,
> +};
[ ... ]
> @@ -5266,6 +5322,7 @@ static int __init kfunc_init(void)
> };
>
> ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &generic_kfunc_set);
> + ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, &user_mem_kfunc_set);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261021195759.119421-1-jolsa@kernel.org?part=2
next prev parent reply other threads:[~2026-10-21 20:22 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 19:57 [RFC bpf-next 0/9] bpf: Add support to allocate user page Jiri Olsa
2026-10-21 19:57 ` [RFC bpf-next 1/9] bpf: Add __srcptr kfunc argument suffix Jiri Olsa
2026-10-21 20:16 ` sashiko-bot
2026-10-21 19:57 ` [RFC bpf-next 2/9] bpf: Add uprobe faultable user copy kfunc Jiri Olsa
2026-10-21 20:22 ` sashiko-bot [this message]
2026-10-21 20:30 ` bot+bpf-ci
2026-10-21 19:57 ` [RFC bpf-next 3/9] mm: Expose locked mprotect operation Jiri Olsa
2026-10-21 20:30 ` bot+bpf-ci
2026-10-22 10:25 ` Lorenzo Stoakes (ARM)
2026-10-22 19:39 ` Jiri Olsa
2026-10-21 19:57 ` [RFC bpf-next 4/9] bpf: Add kfuncs to allocate and seal user pages Jiri Olsa
2026-10-21 20:28 ` sashiko-bot
2026-10-21 20:41 ` bot+bpf-ci
2026-10-21 19:57 ` [RFC bpf-next 5/9] selftests/bpf: Add __srcptr kfunc arguments test Jiri Olsa
2026-10-21 19:57 ` [RFC bpf-next 6/9] selftests/bpf: Add user page allocation test Jiri Olsa
2026-10-21 19:57 ` [RFC bpf-next 7/9] selftests/bpf: Add uprobe user page exec test Jiri Olsa
2026-10-21 19:57 ` [RFC bpf-next 8/9] selftests/bpf: Add faultable user page writes test Jiri Olsa
2026-10-21 19:57 ` [RFC bpf-next 9/9] selftests/bpf: Add user page failures test Jiri Olsa
2026-10-21 20:30 ` bot+bpf-ci
2026-10-21 21:53 ` [RFC bpf-next 0/9] bpf: Add support to allocate user page Alexei Starovoitov
2026-10-22 10:01 ` Jiri Olsa
2026-10-22 10:27 ` Lorenzo Stoakes (ARM)
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=sashiko-outbox-180638@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=liam@infradead.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=memxor@gmail.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=shuah@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