Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
This commit is contained in:
@@ -504,6 +504,7 @@ static void reset_reg_range_values(struct bpf_reg_state *regs, u32 regno)
|
||||
{
|
||||
regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
|
||||
regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
|
||||
regs[regno].value_from_signed = false;
|
||||
regs[regno].min_align = 0;
|
||||
}
|
||||
|
||||
@@ -777,12 +778,13 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off,
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
|
||||
static bool __is_pointer_value(bool allow_ptr_leaks,
|
||||
const struct bpf_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;
|
||||
@@ -791,6 +793,11 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
|
||||
{
|
||||
return __is_pointer_value(env->allow_ptr_leaks, &env->cur_state.regs[regno]);
|
||||
}
|
||||
|
||||
static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
|
||||
int off, int size, bool strict)
|
||||
{
|
||||
@@ -1844,10 +1851,24 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
|
||||
dst_align = dst_reg->min_align;
|
||||
|
||||
/* We don't know anything about what was done to this register, mark it
|
||||
* as unknown.
|
||||
* as unknown. Also, if both derived bounds came from signed/unsigned
|
||||
* mixed compares and one side is unbounded, we cannot really do anything
|
||||
* with them as boundaries cannot be trusted. Thus, arithmetic of two
|
||||
* regs of such kind will get invalidated bounds on the dst side.
|
||||
*/
|
||||
if (min_val == BPF_REGISTER_MIN_RANGE &&
|
||||
max_val == BPF_REGISTER_MAX_RANGE) {
|
||||
if ((min_val == BPF_REGISTER_MIN_RANGE &&
|
||||
max_val == BPF_REGISTER_MAX_RANGE) ||
|
||||
(BPF_SRC(insn->code) == BPF_X &&
|
||||
((min_val != BPF_REGISTER_MIN_RANGE &&
|
||||
max_val == BPF_REGISTER_MAX_RANGE) ||
|
||||
(min_val == BPF_REGISTER_MIN_RANGE &&
|
||||
max_val != BPF_REGISTER_MAX_RANGE) ||
|
||||
(dst_reg->min_value != BPF_REGISTER_MIN_RANGE &&
|
||||
dst_reg->max_value == BPF_REGISTER_MAX_RANGE) ||
|
||||
(dst_reg->min_value == BPF_REGISTER_MIN_RANGE &&
|
||||
dst_reg->max_value != BPF_REGISTER_MAX_RANGE)) &&
|
||||
regs[insn->dst_reg].value_from_signed !=
|
||||
regs[insn->src_reg].value_from_signed)) {
|
||||
reset_reg_range_values(regs, insn->dst_reg);
|
||||
return;
|
||||
}
|
||||
@@ -2035,6 +2056,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
regs[insn->dst_reg].max_value = insn->imm;
|
||||
regs[insn->dst_reg].min_value = insn->imm;
|
||||
regs[insn->dst_reg].min_align = calc_align(insn->imm);
|
||||
regs[insn->dst_reg].value_from_signed = false;
|
||||
}
|
||||
|
||||
} else if (opcode > BPF_END) {
|
||||
@@ -2210,40 +2232,63 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
|
||||
struct bpf_reg_state *false_reg, u64 val,
|
||||
u8 opcode)
|
||||
{
|
||||
bool value_from_signed = true;
|
||||
bool is_range = true;
|
||||
|
||||
switch (opcode) {
|
||||
case BPF_JEQ:
|
||||
/* If this is false then we know nothing Jon Snow, but if it is
|
||||
* true then we know for sure.
|
||||
*/
|
||||
true_reg->max_value = true_reg->min_value = val;
|
||||
is_range = false;
|
||||
break;
|
||||
case BPF_JNE:
|
||||
/* If this is true we know nothing Jon Snow, but if it is false
|
||||
* we know the value for sure;
|
||||
*/
|
||||
false_reg->max_value = false_reg->min_value = val;
|
||||
is_range = false;
|
||||
break;
|
||||
case BPF_JGT:
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
false_reg->min_value = 0;
|
||||
value_from_signed = false;
|
||||
/* fallthrough */
|
||||
case BPF_JSGT:
|
||||
if (true_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(true_reg, 0);
|
||||
if (false_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(false_reg, 0);
|
||||
if (opcode == BPF_JGT) {
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
false_reg->min_value = 0;
|
||||
}
|
||||
/* If this is false then we know the maximum val is val,
|
||||
* otherwise we know the min val is val+1.
|
||||
*/
|
||||
false_reg->max_value = val;
|
||||
false_reg->value_from_signed = value_from_signed;
|
||||
true_reg->min_value = val + 1;
|
||||
true_reg->value_from_signed = value_from_signed;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
false_reg->min_value = 0;
|
||||
value_from_signed = false;
|
||||
/* fallthrough */
|
||||
case BPF_JSGE:
|
||||
if (true_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(true_reg, 0);
|
||||
if (false_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(false_reg, 0);
|
||||
if (opcode == BPF_JGE) {
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
false_reg->min_value = 0;
|
||||
}
|
||||
/* If this is false then we know the maximum value is val - 1,
|
||||
* otherwise we know the mimimum value is val.
|
||||
*/
|
||||
false_reg->max_value = val - 1;
|
||||
false_reg->value_from_signed = value_from_signed;
|
||||
true_reg->min_value = val;
|
||||
true_reg->value_from_signed = value_from_signed;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2251,6 +2296,12 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
|
||||
|
||||
check_reg_overflow(false_reg);
|
||||
check_reg_overflow(true_reg);
|
||||
if (is_range) {
|
||||
if (__is_pointer_value(false, false_reg))
|
||||
reset_reg_range_values(false_reg, 0);
|
||||
if (__is_pointer_value(false, true_reg))
|
||||
reset_reg_range_values(true_reg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Same as above, but for the case that dst_reg is a CONST_IMM reg and src_reg
|
||||
@@ -2260,41 +2311,64 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
|
||||
struct bpf_reg_state *false_reg, u64 val,
|
||||
u8 opcode)
|
||||
{
|
||||
bool value_from_signed = true;
|
||||
bool is_range = true;
|
||||
|
||||
switch (opcode) {
|
||||
case BPF_JEQ:
|
||||
/* If this is false then we know nothing Jon Snow, but if it is
|
||||
* true then we know for sure.
|
||||
*/
|
||||
true_reg->max_value = true_reg->min_value = val;
|
||||
is_range = false;
|
||||
break;
|
||||
case BPF_JNE:
|
||||
/* If this is true we know nothing Jon Snow, but if it is false
|
||||
* we know the value for sure;
|
||||
*/
|
||||
false_reg->max_value = false_reg->min_value = val;
|
||||
is_range = false;
|
||||
break;
|
||||
case BPF_JGT:
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
true_reg->min_value = 0;
|
||||
value_from_signed = false;
|
||||
/* fallthrough */
|
||||
case BPF_JSGT:
|
||||
if (true_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(true_reg, 0);
|
||||
if (false_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(false_reg, 0);
|
||||
if (opcode == BPF_JGT) {
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
true_reg->min_value = 0;
|
||||
}
|
||||
/*
|
||||
* If this is false, then the val is <= the register, if it is
|
||||
* true the register <= to the val.
|
||||
*/
|
||||
false_reg->min_value = val;
|
||||
false_reg->value_from_signed = value_from_signed;
|
||||
true_reg->max_value = val - 1;
|
||||
true_reg->value_from_signed = value_from_signed;
|
||||
break;
|
||||
case BPF_JGE:
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
true_reg->min_value = 0;
|
||||
value_from_signed = false;
|
||||
/* fallthrough */
|
||||
case BPF_JSGE:
|
||||
if (true_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(true_reg, 0);
|
||||
if (false_reg->value_from_signed != value_from_signed)
|
||||
reset_reg_range_values(false_reg, 0);
|
||||
if (opcode == BPF_JGE) {
|
||||
/* Unsigned comparison, the minimum value is 0. */
|
||||
true_reg->min_value = 0;
|
||||
}
|
||||
/* If this is false then constant < register, if it is true then
|
||||
* the register < constant.
|
||||
*/
|
||||
false_reg->min_value = val + 1;
|
||||
false_reg->value_from_signed = value_from_signed;
|
||||
true_reg->max_value = val;
|
||||
true_reg->value_from_signed = value_from_signed;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -2302,6 +2376,12 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
|
||||
|
||||
check_reg_overflow(false_reg);
|
||||
check_reg_overflow(true_reg);
|
||||
if (is_range) {
|
||||
if (__is_pointer_value(false, false_reg))
|
||||
reset_reg_range_values(false_reg, 0);
|
||||
if (__is_pointer_value(false, true_reg))
|
||||
reset_reg_range_values(true_reg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_map_reg(struct bpf_reg_state *regs, u32 regno, u32 id,
|
||||
|
Reference in New Issue
Block a user