From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: Eduard Zingerman <eddyz87@gmail.com>,
bpf@vger.kernel.org, ast@kernel.org, andrii@kernel.org,
daniel@iogearbox.net, kafai@meta.com, kernel-team@meta.com,
memxor@gmail.com
Cc: Mykyta Yatsenko <yatsenko@meta.com>
Subject: Re: [RFC PATCH v1 08/10] bpf: verifier: refactor kfunc specialization
Date: Wed, 8 Oct 2025 19:27:17 +0100 [thread overview]
Message-ID: <bb2eac7d-fe07-4e44-bd21-74115fed02bb@gmail.com> (raw)
In-Reply-To: <bf0c87d7c378f033dd2efc193c86789cfd2604f3.camel@gmail.com>
On 10/3/25 23:08, Eduard Zingerman wrote:
> On Fri, 2025-10-03 at 17:04 +0100, Mykyta Yatsenko wrote:
>
> [...]
>
>> @@ -3354,18 +3344,29 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
>> return err;
>> }
>>
>> + err = btf_distill_func_proto(&env->log, desc_btf,
>> + func_proto, func_name,
>> + &func_model);
>> + if (err)
>> + return err;
>> +
>> + call_imm = kfunc_call_imm(addr, func_id);
>> + /* Check whether the relative offset overflows desc->imm */
>> + if ((unsigned long)(s32)call_imm != call_imm) {
> This error was previously reported only when !bpf_jit_supports_far_kfunc_call().
Sorry for the delayed response.
This condition can only be true if call_imm is a 64 bit address. But if
bpf_jit_supports_far_kfunc_call() is true, call_imm holds func_id which
is u32,
anyway, so we can't hit this error.
>
>> + verbose(env, "address of kernel function %s is out of range\n",
>> + func_name);
>> + return -EINVAL;
>> + }
>> +
>> desc = &tab->descs[tab->nr_descs++];
>> desc->func_id = func_id;
>> - desc->imm = call_imm;
> Nit: no need to move this assignment.
>
>> desc->offset = offset;
>> desc->addr = addr;
>> - err = btf_distill_func_proto(&env->log, desc_btf,
>> - func_proto, func_name,
>> - &desc->func_model);
>> - if (!err)
>> - sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
>> - kfunc_desc_cmp_by_id_off, NULL);
>> - return err;
>> + desc->imm = call_imm;
>> + desc->func_model = func_model;
>> + sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
>> + kfunc_desc_cmp_by_id_off, NULL);
>> + return 0;
>> }
>>
>> static int kfunc_desc_cmp_by_imm_off(const void *a, const void *b)
>> @@ -21822,21 +21823,32 @@ static int fixup_call_args(struct bpf_verifier_env *env)
>> return err;
>> }
>>
>> +static unsigned long kfunc_call_imm(unsigned long func_addr, u32 func_id)
>> +{
>> + if (bpf_jit_supports_far_kfunc_call())
>> + return func_id;
>> +
>> + return BPF_CALL_IMM(func_addr);
>> +}
>> +
>> /* replace a generic kfunc with a specialized version if necessary */
>> -static void specialize_kfunc(struct bpf_verifier_env *env,
>> - u32 func_id, u16 offset, unsigned long *addr)
>> +static void specialize_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_desc *desc)
>> {
>> + struct bpf_prog_aux *prog_aux = env->prog->aux;
>> + struct bpf_kfunc_desc_tab *tab = prog_aux->kfunc_tab;
>> struct bpf_prog *prog = env->prog;
>> bool seen_direct_write;
>> void *xdp_kfunc;
>> bool is_rdonly;
>> + u32 func_id = desc->func_id;
>> + u16 offset = desc->offset;
>> + unsigned long call_imm;
>> + unsigned long addr = 0;
>>
>> if (bpf_dev_bound_kfunc_id(func_id)) {
>> xdp_kfunc = bpf_dev_bound_resolve_kfunc(prog, func_id);
>> - if (xdp_kfunc) {
>> - *addr = (unsigned long)xdp_kfunc;
>> - return;
>> - }
>> + if (xdp_kfunc)
>> + addr = (unsigned long)xdp_kfunc;
>> /* fallback to default kfunc when not supported by netdev */
>> }
> Note: right after this line there is:
>
> if (offset) // this checks if kernel or module BTF is used
> return;
>
> The refactoring changes behavior at this point:
> previously if `offset != 0` the `addr` computed for dev bound kfunc
> would be assigned to `desc->addr`, after the refactoring this is not
> the case.
>
> On the other hand, bpf_dev_bound_kfunc_id() looks up func_id in set8
> xdp_metadata_kfunc_ids, that contains functions only defined for
> kernel BTF.
>
> Hence, I suggest moving this `if (offset) return` as the first check
> in the function, to avoid confusion.
>
>>
>> @@ -21848,21 +21860,28 @@ static void specialize_kfunc(struct bpf_verifier_env *env,
>> is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE);
>>
>> if (is_rdonly)
>> - *addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
>> + addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
>>
>> /* restore env->seen_direct_write to its original value, since
>> * may_access_direct_pkt_data mutates it
>> */
>> env->seen_direct_write = seen_direct_write;
>> + } else if (func_id == special_kfunc_list[KF_bpf_set_dentry_xattr]) {
>> + if (bpf_lsm_has_d_inode_locked(prog))
>> + addr = (unsigned long)bpf_set_dentry_xattr_locked;
>> + } else if (func_id == special_kfunc_list[KF_bpf_remove_dentry_xattr]) {
>> + if (bpf_lsm_has_d_inode_locked(prog))
>> + addr = (unsigned long)bpf_remove_dentry_xattr_locked;
>> }
>>
>> - if (func_id == special_kfunc_list[KF_bpf_set_dentry_xattr] &&
>> - bpf_lsm_has_d_inode_locked(prog))
>> - *addr = (unsigned long)bpf_set_dentry_xattr_locked;
>> + if (!addr) /* Nothing to patch with */
>> + return;
>>
>> - if (func_id == special_kfunc_list[KF_bpf_remove_dentry_xattr] &&
>> - bpf_lsm_has_d_inode_locked(prog))
>> - *addr = (unsigned long)bpf_remove_dentry_xattr_locked;
>> + call_imm = kfunc_call_imm(addr, func_id);
>> + desc->imm = call_imm;
> Nit: desc->imm = kfunc_call_imm(addr, func_id);
>
>> + desc->addr = addr;
>> + sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
>> + kfunc_desc_cmp_by_id_off, NULL);
> Why sorting again?
> Neither `func_id` nor `offset` fields change.
>
>> }
>>
>> static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
>> @@ -21885,7 +21904,7 @@ static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
>> static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>> struct bpf_insn *insn_buf, int insn_idx, int *cnt)
>> {
>> - const struct bpf_kfunc_desc *desc;
>> + struct bpf_kfunc_desc *desc;
>>
>> if (!insn->imm) {
>> verbose(env, "invalid kernel function call not eliminated in verifier pass\n");
>> @@ -21905,6 +21924,8 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>> return -EFAULT;
>> }
>>
>> + specialize_kfunc(env, desc);
>> +
>> if (!bpf_jit_supports_far_kfunc_call())
>> insn->imm = BPF_CALL_IMM(desc->addr);
>> if (insn->off)
next prev parent reply other threads:[~2025-10-08 18:27 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-03 16:04 [RFC PATCH v1 00/10] bpf: Introduce file dynptr Mykyta Yatsenko
2025-10-03 16:04 ` [RFC PATCH v1 01/10] selftests/bpf: remove unnecessary kfunc prototypes Mykyta Yatsenko
2025-10-03 17:46 ` Eduard Zingerman
2025-10-03 16:04 ` [RFC PATCH v1 02/10] bpf: widen dynptr size/offset to 64 bit Mykyta Yatsenko
2025-10-03 18:16 ` Andrii Nakryiko
2025-10-03 18:40 ` Eduard Zingerman
2025-10-03 18:53 ` Mykyta Yatsenko
2025-10-03 16:04 ` [RFC PATCH v1 03/10] lib: extract freader into a separate files Mykyta Yatsenko
2025-10-03 18:16 ` Andrii Nakryiko
2025-10-03 20:04 ` Alexei Starovoitov
2025-10-03 16:04 ` [RFC PATCH v1 04/10] lib/freader: support reading more than 2 folios Mykyta Yatsenko
2025-10-03 18:16 ` Andrii Nakryiko
2025-10-03 18:29 ` Mykyta Yatsenko
2025-10-03 18:46 ` Andrii Nakryiko
2025-10-03 16:04 ` [RFC PATCH v1 05/10] bpf: verifier: centralize const dynptr check in unmark_stack_slots_dynptr() Mykyta Yatsenko
2025-10-03 18:18 ` Andrii Nakryiko
2025-10-03 19:02 ` Eduard Zingerman
2025-10-03 16:04 ` [RFC PATCH v1 06/10] bpf: add plumbing for file-backed dynptr Mykyta Yatsenko
2025-10-03 18:38 ` Andrii Nakryiko
2025-10-03 20:55 ` Eduard Zingerman
2025-10-03 16:04 ` [RFC PATCH v1 07/10] bpf: add kfuncs and helpers support for file dynptrs Mykyta Yatsenko
2025-10-03 18:38 ` Andrii Nakryiko
2025-10-03 18:59 ` Mykyta Yatsenko
2025-10-03 21:35 ` Eduard Zingerman
2025-10-08 0:25 ` Mykyta Yatsenko
2025-10-03 16:04 ` [RFC PATCH v1 08/10] bpf: verifier: refactor kfunc specialization Mykyta Yatsenko
2025-10-03 22:08 ` Eduard Zingerman
2025-10-08 0:35 ` Mykyta Yatsenko
2025-10-08 18:27 ` Mykyta Yatsenko [this message]
2025-10-08 19:15 ` Eduard Zingerman
2025-10-03 16:04 ` [RFC PATCH v1 09/10] bpf: dispatch to sleepable file dynptr Mykyta Yatsenko
2025-10-03 18:45 ` Andrii Nakryiko
2025-10-03 20:10 ` Alexei Starovoitov
2025-10-03 22:17 ` Eduard Zingerman
2025-10-03 16:04 ` [RFC PATCH v1 10/10] selftests/bpf: add file dynptr tests Mykyta Yatsenko
2025-10-03 20:02 ` Andrii Nakryiko
2025-10-06 11:50 ` Mykyta Yatsenko
2025-10-06 16:15 ` Andrii Nakryiko
2025-10-03 22:24 ` Eduard Zingerman
2025-10-06 11:54 ` Mykyta Yatsenko
2025-10-08 0:39 ` Mykyta Yatsenko
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=bb2eac7d-fe07-4e44-bd21-74115fed02bb@gmail.com \
--to=mykyta.yatsenko5@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=kafai@meta.com \
--cc=kernel-team@meta.com \
--cc=memxor@gmail.com \
--cc=yatsenko@meta.com \
/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.