Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[linux-2.6-microblaze.git] / kernel / bpf / verifier.c
index 92a4332..ffc3e53 100644 (file)
@@ -1772,16 +1772,21 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno,
                bitmap_from_u64(mask, stack_mask);
                for_each_set_bit(i, mask, 64) {
                        if (i >= func->allocated_stack / BPF_REG_SIZE) {
-                               /* This can happen if backtracking
-                                * is propagating stack precision where
-                                * caller has larger stack frame
-                                * than callee, but backtrack_insn() should
-                                * have returned -ENOTSUPP.
+                               /* the sequence of instructions:
+                                * 2: (bf) r3 = r10
+                                * 3: (7b) *(u64 *)(r3 -8) = r0
+                                * 4: (79) r4 = *(u64 *)(r10 -8)
+                                * doesn't contain jmps. It's backtracked
+                                * as a single block.
+                                * During backtracking insn 3 is not recognized as
+                                * stack access, so at the end of backtracking
+                                * stack slot fp-8 is still marked in stack_mask.
+                                * However the parent state may not have accessed
+                                * fp-8 and it's "unallocated" stack space.
+                                * In such case fallback to conservative.
                                 */
-                               verbose(env, "BUG spi %d stack_size %d\n",
-                                       i, func->allocated_stack);
-                               WARN_ONCE(1, "verifier backtracking bug");
-                               return -EFAULT;
+                               mark_all_scalars_precise(env, st);
+                               return 0;
                        }
 
                        if (func->stack[i].slot_type[0] != STACK_SPILL) {