[linux-yocto] [PATCH][linux-yocto-4.8] bpf/verifier: Fix states_equal() comparison of pointer and UNKNOWN

Ovidiu Panait ovidiu.panait at windriver.com
Mon Apr 2 05:18:29 PDT 2018


commit 37435f7e80ef9adc32a69013c18f135e3f434244 upstream
commit taken from:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit/?id=37435f7e80ef9adc32a69013c18f135e3f434244

An UNKNOWN_VALUE is not supposed to be derived from a pointer, unless
pointer leaks are allowed.  Therefore, states_equal() must not treat
a state with a pointer in a register as "equal" to a state with an
UNKNOWN_VALUE in that register.

This was fixed differently upstream, but the code around here was
largely rewritten in 4.14 by commit f1174f77b50c "bpf/verifier: rework
value tracking".  The bug can be detected by the bpf/verifier sub-test
"pointer/scalar confusion in state equality check (way 1)".

Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
Cc: Edward Cree <ecree at solarflare.com>
Cc: Jann Horn <jannh at google.com>
Cc: Alexei Starovoitov <ast at kernel.org>
Cc: Daniel Borkmann <daniel at iogearbox.net>
[OP: adjusted context for kernel version 4.8]
Signed-off-by: Ovidiu Panait <ovidiu.panait at windriver.com>
---
 kernel/bpf/verifier.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 48fe5d4da143..d2e228eeb733 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -706,12 +706,13 @@ static int check_ctx_access(struct verifier_env *env, int off, int size,
 	return -EACCES;
 }
 
-static bool is_pointer_value(struct verifier_env *env, int regno)
+static bool __is_pointer_value(bool allow_ptr_leaks,
+                              const struct reg_state *reg)
 {
-	if (env->allow_ptr_leaks)
+       if (allow_ptr_leaks)
 		return false;
 
-	switch (env->cur_state.regs[regno].type) {
+       switch (reg->type) {
 	case UNKNOWN_VALUE:
 	case CONST_IMM:
 		return false;
@@ -720,6 +721,12 @@ static bool is_pointer_value(struct verifier_env *env, int regno)
 	}
 }
 
+static bool is_pointer_value(struct verifier_env *env, int regno)
+{
+       return __is_pointer_value(env->allow_ptr_leaks, &env->cur_state.regs[regno]);
+}
+
+
 static int check_ptr_alignment(struct verifier_env *env, struct reg_state *reg,
 			       int off, int size)
 {
@@ -2147,9 +2154,9 @@ static bool states_equal(struct verifier_state *old, struct verifier_state *cur)
 
 		if (memcmp(rold, rcur, sizeof(*rold)) == 0)
 			continue;
-
 		if (rold->type == NOT_INIT ||
-		    (rold->type == UNKNOWN_VALUE && rcur->type != NOT_INIT))
+		    (rold->type == UNKNOWN_VALUE && rcur->type != NOT_INIT &&
+		    !__is_pointer_value(capable(CAP_SYS_ADMIN), rcur)))
 			continue;
 
 		if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET &&
-- 
2.11.0



More information about the linux-yocto mailing list