Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[sfrench/cifs-2.6.git] / kernel / bpf / verifier.c
index 16ba43352a5ff4a098af7aa9801b6b982f30f4fb..36d1e7339edef90a38f7f3fd3a988a68c55a110f 100644 (file)
@@ -7357,7 +7357,7 @@ static int is_branch32_taken(struct bpf_reg_state *reg, u32 val, u8 opcode)
        case BPF_JSGT:
                if (reg->s32_min_value > sval)
                        return 1;
-               else if (reg->s32_max_value < sval)
+               else if (reg->s32_max_value <= sval)
                        return 0;
                break;
        case BPF_JLT:
@@ -7430,7 +7430,7 @@ static int is_branch64_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
        case BPF_JSGT:
                if (reg->smin_value > sval)
                        return 1;
-               else if (reg->smax_value < sval)
+               else if (reg->smax_value <= sval)
                        return 0;
                break;
        case BPF_JLT:
@@ -9049,7 +9049,11 @@ static bool range_within(struct bpf_reg_state *old,
        return old->umin_value <= cur->umin_value &&
               old->umax_value >= cur->umax_value &&
               old->smin_value <= cur->smin_value &&
-              old->smax_value >= cur->smax_value;
+              old->smax_value >= cur->smax_value &&
+              old->u32_min_value <= cur->u32_min_value &&
+              old->u32_max_value >= cur->u32_max_value &&
+              old->s32_min_value <= cur->s32_min_value &&
+              old->s32_max_value >= cur->s32_max_value;
 }
 
 /* Maximum number of register states that can exist at once */
@@ -11556,30 +11560,28 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                    insn->code == (BPF_ALU | BPF_MOD | BPF_X) ||
                    insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
                        bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
-                       struct bpf_insn mask_and_div[] = {
-                               BPF_MOV32_REG(insn->src_reg, insn->src_reg),
+                       bool isdiv = BPF_OP(insn->code) == BPF_DIV;
+                       struct bpf_insn *patchlet;
+                       struct bpf_insn chk_and_div[] = {
                                /* Rx div 0 -> 0 */
-                               BPF_JMP_IMM(BPF_JNE, insn->src_reg, 0, 2),
+                               BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
+                                            BPF_JNE | BPF_K, insn->src_reg,
+                                            0, 2, 0),
                                BPF_ALU32_REG(BPF_XOR, insn->dst_reg, insn->dst_reg),
                                BPF_JMP_IMM(BPF_JA, 0, 0, 1),
                                *insn,
                        };
-                       struct bpf_insn mask_and_mod[] = {
-                               BPF_MOV32_REG(insn->src_reg, insn->src_reg),
+                       struct bpf_insn chk_and_mod[] = {
                                /* Rx mod 0 -> Rx */
-                               BPF_JMP_IMM(BPF_JEQ, insn->src_reg, 0, 1),
+                               BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
+                                            BPF_JEQ | BPF_K, insn->src_reg,
+                                            0, 1, 0),
                                *insn,
                        };
-                       struct bpf_insn *patchlet;
 
-                       if (insn->code == (BPF_ALU64 | BPF_DIV | BPF_X) ||
-                           insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
-                               patchlet = mask_and_div + (is64 ? 1 : 0);
-                               cnt = ARRAY_SIZE(mask_and_div) - (is64 ? 1 : 0);
-                       } else {
-                               patchlet = mask_and_mod + (is64 ? 1 : 0);
-                               cnt = ARRAY_SIZE(mask_and_mod) - (is64 ? 1 : 0);
-                       }
+                       patchlet = isdiv ? chk_and_div : chk_and_mod;
+                       cnt = isdiv ? ARRAY_SIZE(chk_and_div) :
+                                     ARRAY_SIZE(chk_and_mod);
 
                        new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt);
                        if (!new_prog)