All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt Bobrowski <mattbobrowski@google.com>
To: Viktor Malik <vmalik@redhat.com>
Cc: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Eduard Zingerman <eddyz87@gmail.com>, Song Liu <song@kernel.org>,
	Yonghong Song <yonghong.song@linux.dev>,
	John Fastabend <john.fastabend@gmail.com>,
	KP Singh <kpsingh@kernel.org>,
	Stanislav Fomichev <sdf@fomichev.me>, Hao Luo <haoluo@google.com>,
	Jiri Olsa <jolsa@kernel.org>
Subject: Re: [PATCH bpf-next v4 1/4] bpf: Teach vefier to handle const ptrs as args to kfuncs
Date: Thu, 8 May 2025 09:08:58 +0000	[thread overview]
Message-ID: <aBx0qmVvL84Jb3rf@google.com> (raw)
In-Reply-To: <1497b70f2a948fe29559c6bfb03551a7cc8638f1.1746598898.git.vmalik@redhat.com>

On Wed, May 07, 2025 at 08:40:36AM +0200, Viktor Malik wrote:
> When a kfunc takes a const pointer as an argument, the verifier should
> not check that the memory can be accessed for writing as that may lead
> to rejecting safe programs. Extend the verifier to detect such arguments
> and skip the write access check for them.
> 
> The use-case for this change is passing string literals (i.e. read-only
> maps) to read-only string kfuncs.
> 
> Signed-off-by: Viktor Malik <vmalik@redhat.com>
> ---
>  include/linux/btf.h   |  5 +++++
>  kernel/bpf/verifier.c | 10 ++++++----
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/btf.h b/include/linux/btf.h
> index ebc0c0c9b944..5cb06c65d91f 100644
> --- a/include/linux/btf.h
> +++ b/include/linux/btf.h
> @@ -391,6 +391,11 @@ static inline bool btf_type_is_type_tag(const struct btf_type *t)
>  	return BTF_INFO_KIND(t->info) == BTF_KIND_TYPE_TAG;
>  }
>  
> +static inline bool btf_type_is_const(const struct btf_type *t)
> +{
> +	return BTF_INFO_KIND(t->info) == BTF_KIND_CONST;
> +}

I've seen btf_type_is_* related helpers lean on btf_kind() instead
here, which ultimately just wraps BTF_INFO_KIND() macro.

>  /* union is only a special case of struct:
>   * all its offsetof(member) == 0
>   */
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 54c6953a8b84..e2d74c4d44c1 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -8186,7 +8186,7 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
>  }
>  
>  static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
> -			 u32 regno, u32 mem_size)
> +			 u32 regno, u32 mem_size, bool read_only)

Maybe s/read_only/write_mem_access?

>  {
>  	bool may_be_null = type_may_be_null(reg->type);
>  	struct bpf_reg_state saved_reg;
> @@ -8205,7 +8205,8 @@ static int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg
>  	}
>  
>  	err = check_helper_mem_access(env, regno, mem_size, BPF_READ, true, NULL);
> -	err = err ?: check_helper_mem_access(env, regno, mem_size, BPF_WRITE, true, NULL);
> +	if (!read_only)
> +		err = err ?: check_helper_mem_access(env, regno, mem_size, BPF_WRITE, true, NULL);

For clarity, I'd completely get rid of the ternary operator usage
here. You can short circuit the call to check_helper_mem_access() w/
BPF_WRITE by simply checking the error code value from the preceding
call to check_helper_mem_access() w/ BPF_READ in the branch condition
i.e.

```
err = check_helper_mem_access(..., BPF_READ, ...);
if (!err && write_mem_access)
   err = check_helper_mem_acces(..., BPF_WRITE, ...);
```

>  	if (may_be_null)
>  		*reg = saved_reg;
> @@ -10361,7 +10362,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
>  			ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE);
>  			if (ret < 0)
>  				return ret;
> -			if (check_mem_reg(env, reg, regno, arg->mem_size))
> +			if (check_mem_reg(env, reg, regno, arg->mem_size, false))

For clarity, I'd add: /*write_mem_access=*/false). Same with the below
call to check_mem_reg().

>  				return -EINVAL;
>  			if (!(arg->arg_type & PTR_MAYBE_NULL) && (reg->type & PTR_MAYBE_NULL)) {
>  				bpf_log(log, "arg#%d is expected to be non-NULL\n", i);
> @@ -13252,7 +13253,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
>  					i, btf_type_str(ref_t), ref_tname, PTR_ERR(resolve_ret));
>  				return -EINVAL;
>  			}
> -			ret = check_mem_reg(env, reg, regno, type_size);
> +			ret = check_mem_reg(env, reg, regno, type_size,
> +					    btf_type_is_const(btf_type_by_id(btf, t->type)));
>  			if (ret < 0)
>  				return ret;
>  			break;
> -- 
> 2.49.0
> 

  reply	other threads:[~2025-05-08  9:09 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-07  6:40 [PATCH bpf-next v4 0/4] bpf: Add kfuncs for read-only string operations Viktor Malik
2025-05-07  6:40 ` [PATCH bpf-next v4 1/4] bpf: Teach vefier to handle const ptrs as args to kfuncs Viktor Malik
2025-05-08  9:08   ` Matt Bobrowski [this message]
2025-05-09 16:20     ` Alexei Starovoitov
2025-05-13  6:48       ` Matt Bobrowski
2025-05-13  7:54         ` Viktor Malik
2025-05-13 14:58           ` Alexei Starovoitov
2025-05-13  7:58     ` Viktor Malik
2025-05-07  6:40 ` [PATCH bpf-next v4 2/4] uaccess: Define pagefault lock guard Viktor Malik
2025-05-08 10:00   ` Matt Bobrowski
2025-05-09 18:20     ` Andrii Nakryiko
2025-05-13  6:55       ` Matt Bobrowski
2025-05-07  6:40 ` [PATCH bpf-next v4 3/4] bpf: Add kfuncs for read-only string operations Viktor Malik
2025-05-08  9:41   ` Matt Bobrowski
2025-05-09 16:39     ` Alexei Starovoitov
2025-05-28  9:05       ` Viktor Malik
2025-05-15 12:32     ` Viktor Malik
2025-05-09 18:20   ` Andrii Nakryiko
2025-05-09 21:37     ` Eduard Zingerman
2025-05-09 22:03       ` Andrii Nakryiko
2025-05-15 12:27         ` Viktor Malik
2025-05-15 17:17           ` Andrii Nakryiko
2025-05-16  5:59             ` Viktor Malik
2025-05-16 15:50               ` Andrii Nakryiko
2025-05-07  6:40 ` [PATCH bpf-next v4 4/4] selftests/bpf: Add tests for string kfuncs Viktor Malik

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=aBx0qmVvL84Jb3rf@google.com \
    --to=mattbobrowski@google.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=sdf@fomichev.me \
    --cc=song@kernel.org \
    --cc=vmalik@redhat.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 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.