public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii@kernel.org>
To: <bpf@vger.kernel.org>, <ast@kernel.org>, <daniel@iogearbox.net>
Cc: <andrii@kernel.org>, <kernel-team@fb.com>
Subject: [PATCH bpf-next 7/7] bpf: unify PTR_TO_MAP_{KEY,VALUE} with default case in regsafe()
Date: Thu, 22 Dec 2022 21:49:21 -0800	[thread overview]
Message-ID: <20221223054921.958283-8-andrii@kernel.org> (raw)
In-Reply-To: <20221223054921.958283-1-andrii@kernel.org>

Make default case in regsafe() safer. Instead of doing byte-by-byte
comparison, take into account ID remapping and also range and var_off
checks. For most of registers range and var_off will be zero (not set),
which doesn't matter. For some, like PTR_TO_MAP_{KEY,VALUE}, this
generalized logic is exactly matching what regsafe() was doing as
a special case. But in any case, if register has id and/or ref_obj_id
set, check it using check_ids() logic, taking into account idmap.

With these changes, default case should be handling most registers more
correctly, and even for future register would be a good default. For some
special cases, like PTR_TO_PACKET, one would still need to implement extra
checks (like special handling of reg->range) to get better state
equivalence, but default logic shouldn't be wrong.

With these changes veristat shows no difference in verifier stats across
selftests and Cilium BPF programs (which is a good thing).

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
---
 kernel/bpf/verifier.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b23812d2bb49..7e0fa3924f01 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12919,8 +12919,8 @@ static int check_btf_info(struct bpf_verifier_env *env,
 }
 
 /* check %cur's range satisfies %old's */
-static bool range_within(struct bpf_reg_state *old,
-			 struct bpf_reg_state *cur)
+static bool range_within(const struct bpf_reg_state *old,
+			 const struct bpf_reg_state *cur)
 {
 	return old->umin_value <= cur->umin_value &&
 	       old->umax_value >= cur->umax_value &&
@@ -13073,6 +13073,17 @@ static bool regs_exact(const struct bpf_reg_state *rold,
 	       check_ids(rold->ref_obj_id, rcur->ref_obj_id, idmap);
 }
 
+static bool regs_equal(const struct bpf_reg_state *rold,
+		       const struct bpf_reg_state *rcur,
+		       struct bpf_id_pair *idmap)
+{
+	return memcmp(rold, rcur, offsetof(struct bpf_reg_state, var_off)) == 0 &&
+	       range_within(rold, rcur) &&
+	       tnum_in(rold->var_off, rcur->var_off) &&
+	       check_ids(rold->id, rcur->id, idmap) &&
+	       check_ids(rold->ref_obj_id, rcur->ref_obj_id, idmap);
+}
+
 /* Returns true if (rold safe implies rcur safe) */
 static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
 		    struct bpf_reg_state *rcur, struct bpf_id_pair *idmap)
@@ -13121,15 +13132,6 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
 		/* new val must satisfy old val knowledge */
 		return range_within(rold, rcur) &&
 		       tnum_in(rold->var_off, rcur->var_off);
-	case PTR_TO_MAP_KEY:
-	case PTR_TO_MAP_VALUE:
-		/* If the new min/max/var_off satisfy the old ones and
-		 * everything else matches, we are OK.
-		 */
-		return memcmp(rold, rcur, offsetof(struct bpf_reg_state, var_off)) == 0 &&
-		       range_within(rold, rcur) &&
-		       tnum_in(rold->var_off, rcur->var_off) &&
-		       check_ids(rold->id, rcur->id, idmap);
 	case PTR_TO_PACKET_META:
 	case PTR_TO_PACKET:
 		/* We must have at least as much range as the old ptr
@@ -13157,7 +13159,7 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
 		 */
 		return regs_exact(rold, rcur, idmap) && rold->frameno == rcur->frameno;
 	default:
-		return regs_exact(rold, rcur, idmap);
+		return regs_equal(rold, rcur, idmap);
 	}
 }
 
-- 
2.30.2


  parent reply	other threads:[~2022-12-23  5:49 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-23  5:49 [PATCH bpf-next 0/7] BPF verifier state equivalence checks improvements Andrii Nakryiko
2022-12-23  5:49 ` [PATCH bpf-next 1/7] bpf: teach refsafe() to take into account ID remapping Andrii Nakryiko
2022-12-23  5:49 ` [PATCH bpf-next 2/7] bpf: reorganize struct bpf_reg_state fields Andrii Nakryiko
2022-12-23  5:49 ` [PATCH bpf-next 3/7] bpf: generalize MAYBE_NULL vs non-MAYBE_NULL rule Andrii Nakryiko
2022-12-23  5:49 ` [PATCH bpf-next 4/7] bpf: reject non-exact register type matches in regsafe() Andrii Nakryiko
2022-12-23  5:49 ` [PATCH bpf-next 5/7] bpf: perform byte-by-byte comparison only when necessary " Andrii Nakryiko
2022-12-23  5:49 ` [PATCH bpf-next 6/7] bpf: fix regs_exact() logic in regsafe() to remap IDs correctly Andrii Nakryiko
2022-12-23  5:49 ` Andrii Nakryiko [this message]
2022-12-28  2:00   ` [PATCH bpf-next 7/7] bpf: unify PTR_TO_MAP_{KEY,VALUE} with default case in regsafe() Alexei Starovoitov
2022-12-29 21:59     ` Andrii Nakryiko
2022-12-30  2:19       ` Alexei Starovoitov
2023-01-03 22:04         ` Andrii Nakryiko
2023-01-04 22:35           ` Alexei Starovoitov
2023-01-04 23:03             ` Andrii Nakryiko
2023-01-05  0:14               ` Alexei Starovoitov
2023-01-11 19:08                 ` Andrii Nakryiko
2022-12-28  2:10 ` [PATCH bpf-next 0/7] BPF verifier state equivalence checks improvements patchwork-bot+netdevbpf

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=20221223054921.958283-8-andrii@kernel.org \
    --to=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@fb.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox