All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: Menglong Dong <menglong8.dong@gmail.com>, andrii@kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, john.fastabend@gmail.com,
	martin.lau@linux.dev, song@kernel.org, kpsingh@kernel.org,
	sdf@google.com, haoluo@google.com, jolsa@kernel.org,
	bpf@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH bpf-next] bpf: make the verifier trace the "not qeual" for regs
Date: Sun, 10 Dec 2023 21:09:32 -0800	[thread overview]
Message-ID: <4457e84f-4417-4a60-a814-9288b0756d91@linux.dev> (raw)
In-Reply-To: <20231210130001.2050847-1-menglong8.dong@gmail.com>


On 12/10/23 5:00 AM, Menglong Dong wrote:
> We can derive some new information for BPF_JNE in regs_refine_cond_op().
> Take following code for example:
>
>    /* The type of "a" is u16 */
>    if (a > 0 && a < 100) {
>      /* the range of the register for a is [0, 99], not [1, 99],
>       * and will cause the following error:
>       *
>       *   invalid zero-sized read
>       *
>       * as a can be 0.
>       */
>      bpf_skb_store_bytes(skb, xx, xx, a, 0);
>    }

Could you have a C test to demonstrate this example?
Also, you should have a set of inline asm code (progs/verifier*.c)
to test various cases as in mark_reg32_not_equal() and
mark_reg_not_equal().

>
> In the code above, "a > 0" will be compiled to "jmp xxx if a == 0". In the
> TRUE branch, the dst_reg will be marked as known to 0. However, in the
> fallthrough(FALSE) branch, the dst_reg will not be handled, which makes
> the [min, max] for a is [0, 99], not [1, 99].
>
> For BPF_JNE, we can reduce the range of the dst reg if the src reg is a
> const and is exactly the edge of the dst reg.
>
> Signed-off-by: Menglong Dong <menglong8.dong@gmail.com>
> ---
>   kernel/bpf/verifier.c | 45 ++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 727a59e4a647..7b074ac93190 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -1764,6 +1764,40 @@ static void __mark_reg_const_zero(struct bpf_reg_state *reg)
>   	reg->type = SCALAR_VALUE;
>   }
>   
> +#define CHECK_REG_MIN(value)			\
> +do {						\
> +	if ((value) == (typeof(value))imm)	\
> +		value++;			\
> +} while (0)
> +
> +#define CHECK_REG_MAX(value)			\
> +do {						\
> +	if ((value) == (typeof(value))imm)	\
> +		value--;			\
> +} while (0)
> +
> +static void mark_reg32_not_equal(struct bpf_reg_state *reg, u64 imm)
> +{

What if reg->s32_min_value == imm and reg->s32_max_value == imm?
Has this been handled in previous verifier logic?

> +		CHECK_REG_MIN(reg->s32_min_value);
> +		CHECK_REG_MAX(reg->s32_max_value);
> +		CHECK_REG_MIN(reg->u32_min_value);
> +		CHECK_REG_MAX(reg->u32_max_value);
> +}
> +
> +static void mark_reg_not_equal(struct bpf_reg_state *reg, u64 imm)
> +{
> +		CHECK_REG_MIN(reg->smin_value);
> +		CHECK_REG_MAX(reg->smax_value);
> +
> +		CHECK_REG_MIN(reg->umin_value);
> +		CHECK_REG_MAX(reg->umax_value);
> +
> +		CHECK_REG_MIN(reg->s32_min_value);
> +		CHECK_REG_MAX(reg->s32_max_value);
> +		CHECK_REG_MIN(reg->u32_min_value);
> +		CHECK_REG_MAX(reg->u32_max_value);
> +}
> +
>   static void mark_reg_known_zero(struct bpf_verifier_env *env,
>   				struct bpf_reg_state *regs, u32 regno)
>   {
> @@ -14332,7 +14366,16 @@ static void regs_refine_cond_op(struct bpf_reg_state *reg1, struct bpf_reg_state
>   		}
>   		break;
>   	case BPF_JNE:
> -		/* we don't derive any new information for inequality yet */
> +		/* try to recompute the bound of reg1 if reg2 is a const and
> +		 * is exactly the edge of reg1.
> +		 */
> +		if (is_reg_const(reg2, is_jmp32)) {
> +			val = reg_const_value(reg2, is_jmp32);
> +			if (is_jmp32)
> +				mark_reg32_not_equal(reg1, val);
> +			else
> +				mark_reg_not_equal(reg1, val);
> +		}
>   		break;
>   	case BPF_JSET:
>   		if (!is_reg_const(reg2, is_jmp32))

  reply	other threads:[~2023-12-11  5:09 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-10 13:00 [PATCH bpf-next] bpf: make the verifier trace the "not qeual" for regs Menglong Dong
2023-12-11  5:09 ` Yonghong Song [this message]
2023-12-11  9:39   ` Menglong Dong
2023-12-11 15:03     ` Yonghong Song
2023-12-11 19:15 ` Andrii Nakryiko
2023-12-12  2:15   ` Menglong Dong
2023-12-12  3:51     ` Andrii Nakryiko

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=4457e84f-4417-4a60-a814-9288b0756d91@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=menglong8.dong@gmail.com \
    --cc=sdf@google.com \
    --cc=song@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 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.