All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ihor Solodrai <ihor.solodrai@linux.dev>
To: Eduard Zingerman <eddyz87@gmail.com>, chenyuan_fl@163.com
Cc: andrii@kernel.org, ast@kernel.org, bot+bpf-ci@kernel.org,
	bpf@vger.kernel.org, chenyuan@kylinos.cn, clm@meta.com,
	daniel@iogearbox.net, jolsa@kernel.org,
	linux-kernel@vger.kernel.org, martin.lau@kernel.org,
	martin.lau@linux.dev, memxor@gmail.com, song@kernel.org,
	yonghong.song@linux.dev
Subject: Re: [PATCH bpf v5 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref
Date: Mon, 8 Jun 2026 18:18:24 -0700	[thread overview]
Message-ID: <118b0bc7-5126-465d-993c-3b25e331e2cf@linux.dev> (raw)
In-Reply-To: <49c36dc0f52bd05d0f8c055e3d3e96992ae716a6.camel@gmail.com>

On 6/8/26 6:00 PM, Eduard Zingerman wrote:
> On Mon, 2026-06-08 at 17:54 -0700, Ihor Solodrai wrote:
>> On 6/8/26 7:26 AM, chenyuan_fl@163.com wrote:
>>> From: Yuan Chen <chenyuan@kylinos.cn>
>>>
>>> When a module kfunc declares an implicit struct bpf_prog_aux * argument,
>>> the verifier must identify it so the kernel injects env->prog->aux into
>>> the correct register at runtime.  The original check used
>>> is_kfunc_arg_prog_aux() which calls btf_types_are_same() to compare the
>>> module BTF type against vmlinux.
>>>
>>> Root Cause
>>>
>>> This issue was triggered by pahole 1.30 generating module BTF with
>>> incorrect type information, which caused the kernel's distilled base
>>> BTF deduplication for modules to fail.  As a result, the module retained
>>> its own copy of struct bpf_prog_aux with a different BTF ID than
>>> vmlinux's definition.  While pahole 1.31 fixed the BTF generation issue,
>>> the kernel must be robust against such inconsistencies: a BTF mismatch
>>> should result in a clean rejection, not a kernel crash or information
>>> disclosure.
>>>
>>> When the distilled base dedup fails and btf_types_are_same() cannot
>>> match the module's bpf_prog_aux type against vmlinux's,
>>> is_kfunc_arg_prog_aux() returned false and the code fell through
>>> silently without setting arg_prog.  The kfunc then received whatever
>>> value was in the argument register and dereferenced it as a
>>> bpf_prog_aux pointer, leading to:
>>>
>>>   BUG: kernel invalid pointer dereference, address: 00000000000009e2
>>>   RIP: bpf_prog_get_assoc_struct_ops+0xa/0xc0
>>>   RDI: 0x000000000000046d (stale register value)
>>>
>>> In the observed crash the stale value was the process PID, causing a
>>> dereference within the unmapped NULL page.  However, an attacker able
>>> to control the register value -- for example by writing a BPF program
>>> that explicitly sets R2 before calling a KF_IMPLICIT_ARGS kfunc --
>>> could redirect the dereference to arbitrary kernel memory, turning
>>> this into an information disclosure.  The fix ensures the verifier
>>> either validates and injects the correct bpf_prog_aux pointer, or
>>> rejects the program outright -- no silent fallthrough that could
>>> be exploited.
>>>
>>> Crash Stack Trace
>>>
>>>   PID: 1133     TASK: ffff8881057d3900  CPU: 3    COMMAND: "test_progs"
>>>    #0 machine_kexec at ffffffff812f6e26
>>>    #1 __crash_kexec at ffffffff8145a788
>>>    #2 crash_kexec at ffffffff8145ac24
>>>    #3 oops_end at ffffffff812bb67c
>>>    #4 page_fault_oops at ffffffff813053a1
>>>    #5 exc_page_fault at ffffffff828e60a1
>>>    #6 asm_exc_page_fault at ffffffff810012a6
>>>       [exception RIP: bpf_prog_get_assoc_struct_ops+10]
>>>       RIP: ffffffff815c024a  RSP: ffffc90001b57e48  RFLAGS: 00010283
>>>       RAX: ffff8881057d3900  RBX: ffffc90001b57e68  RCX: ffff8881057d3900
>>>       RDX: 0000607d4d1768b8  RSI: 000000000000046d  RDI: 000000000000046d
>>>    #7 bpf_kfunc_multi_st_ops_test_1_assoc at ffffffffc0013a85 [bpf_testmod]
>>>    #8 bpf_trace_run2 at ffffffff814f8332
>>>    #9 __traceiter_sys_enter at ffffffff81415f45
>>>   #10 trace_syscall_enter at ffffffff81416735
>>>   #11 do_syscall_64 at ffffffff828e06a1
>>>
>>> Fix
>>>
>>> Split the combined is_kfunc_arg_ignore() || is_kfunc_arg_implicit()
>>> check in check_kfunc_args() so that an implicit argument reaching
>>> is_kfunc_arg_implicit() without being handled by a prior handler is
>>> rejected with -EFAULT, instead of silently skipped.  Existing implicit
>>>       args in bpf_fixup_kfunc_call() (obj_new, percpu_obj_new, obj_drop,
>>>       percpu_obj_drop, refcount_acquire, list_push, rbtree_add) are
>>>       explicitly allowed.
>>>
>>> Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
>>> Fixes: 64e1360524b9 ("bpf: Verifier support for KF_IMPLICIT_ARGS")
>>> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
>>> ---
>>>  kernel/bpf/verifier.c | 20 +++++++++++++++++++-
>>>  1 file changed, 19 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>>> index 8ed484cb1a8a..91aaed7a5eeb 100644
>>> --- a/kernel/bpf/verifier.c
>>> +++ b/kernel/bpf/verifier.c
>>> @@ -11885,9 +11885,27 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
>>>  			continue;
>>>  		}
>>>  
>>> -		if (is_kfunc_arg_ignore(btf, &args[i]) || is_kfunc_arg_implicit(meta, i))
>>> +		if (is_kfunc_arg_ignore(btf, &args[i]))
>>>  			continue;
>>>  
>>> +		if (is_kfunc_arg_implicit(meta, i)) {
>>> +			/* kfuncs with implicit args (e.g. 'off' parameter)
>>> +			 * handled during verification in bpf_fixup_kfunc_call():
>>> +			 * obj_new, percpu_obj_new, obj_drop, percpu_obj_drop,
>>> +			 * refcount_acquire, list_push, rbtree_add. Don't flag them. */
>>> +			if (is_bpf_obj_new_kfunc(meta->func_id) ||
>>> +			    is_bpf_percpu_obj_new_kfunc(meta->func_id) ||
>>> +			    is_bpf_obj_drop_kfunc(meta->func_id) ||
>>> +			    is_bpf_percpu_obj_drop_kfunc(meta->func_id) ||
>>> +			    is_bpf_refcount_acquire_kfunc(meta->func_id) ||
>>> +			    is_bpf_list_push_kfunc(meta->func_id) ||
>>> +			    is_bpf_rbtree_add_kfunc(meta->func_id))
>>
>> Is the goal here to have a nice error message?
>>
>> I think this will fail for other functions like bpf_wq_set_callback().
>> For a proper check, the list must include every single kfunc with KF_IMPLICIT_ARGS, no?
>>
>> If we go this route, then the list of flagged kfuncs can be collected automatically.
>> I'm not sure we actually want to do this.
> 
> The calls to functions with implicit arguments are patched by
> bpf_fixup_kfunc_call(). As far as I understand, this function:
> - handles functions with implicit bpf_prog_aux generically
> - handles the functions listed above on a case-by-case basis.
> 
> The goal is not to have a nice error message, but to prevent runtime
> from reading garbage from a register.

In check_kfunc_args() we only needed to know whether the arg is implicit,
independent of its type, which is_kfunc_arg_implicit() already does. To skip it.

For vmlinux kernel kfuncs this should be enough, I think.

To properly harden against reading garbage for a *module* kfunc, I think the 
verifier would have to check for the specific BTF type, e.g. "are we patching a 
struct bpf_prog_aux pointer?".

It could be done immediately before patching, but at that point the verification is
complete, right?..

Other than that we'd have to somehow pass through from check_kfunc_args() to
bpf_fixup_kfunc_call() information like "arg 1 of this kfunc can be patched to prog_aux" etc.
We sort of do that already with the meta->arg_prog = true

In a module one can define arbitrary kfuncs and add KF_IMPLICIT_ARGS to them, so
proper hardening needs to be generic.

I think this boils down to whether we want to error-check module kfuncs or not.
Not sure what the verifier strategy is here, but my understanding is that in general
a custom module can easily make kernel read garbage, and it's not a kernel's problem.

> 
>>
>>> +				continue;
>>> +			verbose(env, "%s unrecognized implicit argument, possible BTF mismatch\n",
>>> +				reg_arg_name(env, argno));
>>> +			return -EFAULT;
>>> +		}
>>> +
>>>  		t = btf_type_skip_modifiers(btf, args[i].type, NULL);
>>>  
>>>  		if (btf_type_is_scalar(t)) {


  reply	other threads:[~2026-06-09  1:18 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-07  8:09 [PATCH] bpf: fix btf_types_are_same for cross-BTF type comparison chenyuan_fl
2026-04-07  8:58 ` Leon Hwang
2026-04-07  9:01 ` bot+bpf-ci
2026-04-07 11:19 ` Alan Maguire
2026-05-15 18:27 ` Ihor Solodrai
2026-06-01  6:46 ` [PATCH bpf v2 0/2] bpf: Fix kfunc implicit arg injection and add selftest chenyuan_fl
2026-06-01  6:46   ` [PATCH bpf v2 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref chenyuan_fl
2026-06-01  7:42     ` bot+bpf-ci
2026-06-01 19:32       ` Eduard Zingerman
2026-06-02  8:58         ` [PATCH bpf v3 0/2] bpf: Fix kfunc implicit arg injection and add selftest chenyuan_fl
2026-06-02  8:58           ` [PATCH bpf v3 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref chenyuan_fl
2026-06-02  9:23             ` sashiko-bot
2026-06-02  9:44             ` bot+bpf-ci
2026-06-02 18:52             ` Ihor Solodrai
2026-06-04  9:14               ` chenyuan
2026-06-04 10:21                 ` Alan Maguire
2026-06-09  0:46                   ` Ihor Solodrai
2026-06-02  8:58           ` [PATCH bpf v3 2/2] selftests/bpf: Add regression test for kfunc implicit arg injection chenyuan_fl
2026-06-02  9:31             ` sashiko-bot
2026-06-02  9:44             ` bot+bpf-ci
2026-06-02  9:38         ` [PATCH bpf v4 0/2] bpf: Fix kfunc implicit arg injection and add selftest chenyuan_fl
2026-06-02  9:38           ` [PATCH bpf v4 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref chenyuan_fl
2026-06-02  9:58             ` sashiko-bot
2026-06-02 10:42             ` bot+bpf-ci
2026-06-05  0:42             ` Eduard Zingerman
2026-06-02  9:38           ` [PATCH bpf v4 2/2] selftests/bpf: Add regression test for kfunc implicit arg injection chenyuan_fl
2026-06-02 10:06             ` sashiko-bot
2026-06-02 10:27             ` bot+bpf-ci
2026-06-02 17:36             ` kernel test robot
2026-06-02 18:37             ` kernel test robot
2026-06-05  1:29             ` Eduard Zingerman
2026-06-08 14:26           ` [PATCH bpf v5 0/2] bpf: Fix kfunc implicit arg injection and add selftest chenyuan_fl
2026-06-08 14:26             ` [PATCH bpf v5 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref chenyuan_fl
2026-06-08 14:47               ` sashiko-bot
2026-06-08 14:52               ` bot+bpf-ci
2026-06-08 17:28               ` Eduard Zingerman
2026-06-09  0:54               ` Ihor Solodrai
2026-06-09  1:00                 ` Eduard Zingerman
2026-06-09  1:18                   ` Ihor Solodrai [this message]
2026-06-09  6:20                     ` Eduard Zingerman
2026-06-08 14:26             ` [PATCH bpf v5 2/2] selftests/bpf: strengthen bpf_kfunc_implicit_arg to verify aux injection chenyuan_fl
2026-06-08 14:53               ` sashiko-bot
2026-06-08 17:34               ` Eduard Zingerman
2026-06-09  0:59               ` Ihor Solodrai
2026-06-08 19:58             ` [PATCH bpf v5 0/2] bpf: Fix kfunc implicit arg injection and add selftest Alexei Starovoitov
2026-06-09 12:52             ` [PATCH bpf v6 " chenyuan_fl
2026-06-09 12:52               ` [PATCH bpf v6 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref chenyuan_fl
2026-06-09 13:08                 ` sashiko-bot
2026-06-09 13:32                 ` bot+bpf-ci
2026-06-09 12:52               ` [PATCH bpf v6 2/2] selftests/bpf: strengthen bpf_kfunc_implicit_arg to verify aux injection chenyuan_fl
2026-06-09 12:59                 ` sashiko-bot
2026-06-01 17:12     ` [PATCH bpf v2 1/2] bpf: Fix kfunc implicit arg inject type detection to prevent invalid pointer deref Yonghong Song
2026-06-01 21:36     ` Eduard Zingerman
2026-06-01  6:46   ` [PATCH bpf v2 2/2] selftests/bpf: Add regression test for kfunc implicit arg injection with stale register chenyuan_fl
2026-06-01  7:08     ` sashiko-bot
2026-06-01 17:17     ` Yonghong Song

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=118b0bc7-5126-465d-993c-3b25e331e2cf@linux.dev \
    --to=ihor.solodrai@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bot+bpf-ci@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=chenyuan@kylinos.cn \
    --cc=chenyuan_fl@163.com \
    --cc=clm@meta.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martin.lau@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=song@kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.