All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduard Zingerman <eddyz87@gmail.com>
To: Mykyta Yatsenko <mykyta.yatsenko5@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: Fri, 03 Oct 2025 15:08:44 -0700	[thread overview]
Message-ID: <bf0c87d7c378f033dd2efc193c86789cfd2604f3.camel@gmail.com> (raw)
In-Reply-To: <20251003160416.585080-9-mykyta.yatsenko5@gmail.com>

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().

> +		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)

  reply	other threads:[~2025-10-03 22:08 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 [this message]
2025-10-08  0:35     ` Mykyta Yatsenko
2025-10-08 18:27     ` Mykyta Yatsenko
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=bf0c87d7c378f033dd2efc193c86789cfd2604f3.camel@gmail.com \
    --to=eddyz87@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kafai@meta.com \
    --cc=kernel-team@meta.com \
    --cc=memxor@gmail.com \
    --cc=mykyta.yatsenko5@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.