On 2018-04-02 8:18 AM, Ovidiu Panait wrote:
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 <b...@decadent.org.uk>
Cc: Edward Cree <ec...@solarflare.com>
Cc: Jann Horn <ja...@google.com>
Cc: Alexei Starovoitov <a...@kernel.org>
Cc: Daniel Borkmann <dan...@iogearbox.net>
[OP: adjusted context for kernel version 4.8]

merged.

Bruce

Signed-off-by: Ovidiu Panait <ovidiu.pan...@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 &&


--
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to