return 0;
 }
 
+static int evaluate_reg_imm_alu_unknown(struct bpf_verifier_env *env,
+                                       struct bpf_insn *insn)
+{
+       struct bpf_reg_state *regs = env->cur_state.regs;
+       struct bpf_reg_state *dst_reg = ®s[insn->dst_reg];
+       struct bpf_reg_state *src_reg = ®s[insn->src_reg];
+       u8 opcode = BPF_OP(insn->code);
+       s64 imm_log2 = __ilog2_u64((long long)dst_reg->imm);
+
+       /* BPF_X code with src_reg->type UNKNOWN_VALUE here. */
+       if (src_reg->imm > 0 && dst_reg->imm) {
+               switch (opcode) {
+               case BPF_ADD:
+                       /* dreg += sreg
+                        * where both have zero upper bits. Adding them
+                        * can only result making one more bit non-zero
+                        * in the larger value.
+                        * Ex. 0xffff (imm=48) + 1 (imm=63) = 0x10000 (imm=47)
+                        *     0xffff (imm=48) + 0xffff = 0x1fffe (imm=47)
+                        */
+                       dst_reg->imm = min(src_reg->imm, 63 - imm_log2);
+                       dst_reg->imm--;
+                       break;
+               case BPF_AND:
+                       /* dreg &= sreg
+                        * AND can not extend zero bits only shrink
+                        * Ex.  0x00..00ffffff
+                        *    & 0x0f..ffffffff
+                        *     ----------------
+                        *      0x00..00ffffff
+                        */
+                       dst_reg->imm = max(src_reg->imm, 63 - imm_log2);
+                       break;
+               case BPF_OR:
+                       /* dreg |= sreg
+                        * OR can only extend zero bits
+                        * Ex.  0x00..00ffffff
+                        *    | 0x0f..ffffffff
+                        *     ----------------
+                        *      0x0f..00ffffff
+                        */
+                       dst_reg->imm = min(src_reg->imm, 63 - imm_log2);
+                       break;
+               case BPF_SUB:
+               case BPF_MUL:
+               case BPF_RSH:
+               case BPF_LSH:
+                       /* These may be flushed out later */
+               default:
+                       mark_reg_unknown_value(regs, insn->dst_reg);
+               }
+       } else {
+               mark_reg_unknown_value(regs, insn->dst_reg);
+       }
+
+       dst_reg->type = UNKNOWN_VALUE;
+       return 0;
+}
+
 static int evaluate_reg_imm_alu(struct bpf_verifier_env *env,
                                struct bpf_insn *insn)
 {
        u8 opcode = BPF_OP(insn->code);
        u64 dst_imm = dst_reg->imm;
 
+       if (BPF_SRC(insn->code) == BPF_X && src_reg->type == UNKNOWN_VALUE)
+               return evaluate_reg_imm_alu_unknown(env, insn);
+
        /* dst_reg->type == CONST_IMM here. Simulate execution of insns
         * containing ALU ops. Don't care about overflow or negative
         * values, just add/sub/... them; registers are in u64.