Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Alexei Starovoitov says: ==================== pull-request: bpf 2019-04-25 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) the bpf verifier fix to properly mark registers in all stack frames, from Paul. 2) preempt_enable_no_resched->preempt_enable fix, from Peter. 3) other misc fixes. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -4138,15 +4138,35 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __find_good_pkt_pointers(struct bpf_func_state *state,
|
||||
struct bpf_reg_state *dst_reg,
|
||||
enum bpf_reg_type type, u16 new_range)
|
||||
{
|
||||
struct bpf_reg_state *reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_BPF_REG; i++) {
|
||||
reg = &state->regs[i];
|
||||
if (reg->type == type && reg->id == dst_reg->id)
|
||||
/* keep the maximum range already checked */
|
||||
reg->range = max(reg->range, new_range);
|
||||
}
|
||||
|
||||
bpf_for_each_spilled_reg(i, state, reg) {
|
||||
if (!reg)
|
||||
continue;
|
||||
if (reg->type == type && reg->id == dst_reg->id)
|
||||
reg->range = max(reg->range, new_range);
|
||||
}
|
||||
}
|
||||
|
||||
static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
|
||||
struct bpf_reg_state *dst_reg,
|
||||
enum bpf_reg_type type,
|
||||
bool range_right_open)
|
||||
{
|
||||
struct bpf_func_state *state = vstate->frame[vstate->curframe];
|
||||
struct bpf_reg_state *regs = state->regs, *reg;
|
||||
u16 new_range;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
if (dst_reg->off < 0 ||
|
||||
(dst_reg->off == 0 && range_right_open))
|
||||
@@ -4211,20 +4231,9 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate,
|
||||
* the range won't allow anything.
|
||||
* dst_reg->off is known < MAX_PACKET_OFF, therefore it fits in a u16.
|
||||
*/
|
||||
for (i = 0; i < MAX_BPF_REG; i++)
|
||||
if (regs[i].type == type && regs[i].id == dst_reg->id)
|
||||
/* keep the maximum range already checked */
|
||||
regs[i].range = max(regs[i].range, new_range);
|
||||
|
||||
for (j = 0; j <= vstate->curframe; j++) {
|
||||
state = vstate->frame[j];
|
||||
bpf_for_each_spilled_reg(i, state, reg) {
|
||||
if (!reg)
|
||||
continue;
|
||||
if (reg->type == type && reg->id == dst_reg->id)
|
||||
reg->range = max(reg->range, new_range);
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= vstate->curframe; i++)
|
||||
__find_good_pkt_pointers(vstate->frame[i], dst_reg, type,
|
||||
new_range);
|
||||
}
|
||||
|
||||
/* compute branch direction of the expression "if (reg opcode val) goto target;"
|
||||
@@ -4698,6 +4707,22 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state,
|
||||
}
|
||||
}
|
||||
|
||||
static void __mark_ptr_or_null_regs(struct bpf_func_state *state, u32 id,
|
||||
bool is_null)
|
||||
{
|
||||
struct bpf_reg_state *reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_BPF_REG; i++)
|
||||
mark_ptr_or_null_reg(state, &state->regs[i], id, is_null);
|
||||
|
||||
bpf_for_each_spilled_reg(i, state, reg) {
|
||||
if (!reg)
|
||||
continue;
|
||||
mark_ptr_or_null_reg(state, reg, id, is_null);
|
||||
}
|
||||
}
|
||||
|
||||
/* The logic is similar to find_good_pkt_pointers(), both could eventually
|
||||
* be folded together at some point.
|
||||
*/
|
||||
@@ -4705,10 +4730,10 @@ static void mark_ptr_or_null_regs(struct bpf_verifier_state *vstate, u32 regno,
|
||||
bool is_null)
|
||||
{
|
||||
struct bpf_func_state *state = vstate->frame[vstate->curframe];
|
||||
struct bpf_reg_state *reg, *regs = state->regs;
|
||||
struct bpf_reg_state *regs = state->regs;
|
||||
u32 ref_obj_id = regs[regno].ref_obj_id;
|
||||
u32 id = regs[regno].id;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
if (ref_obj_id && ref_obj_id == id && is_null)
|
||||
/* regs[regno] is in the " == NULL" branch.
|
||||
@@ -4717,17 +4742,8 @@ static void mark_ptr_or_null_regs(struct bpf_verifier_state *vstate, u32 regno,
|
||||
*/
|
||||
WARN_ON_ONCE(release_reference_state(state, id));
|
||||
|
||||
for (i = 0; i < MAX_BPF_REG; i++)
|
||||
mark_ptr_or_null_reg(state, ®s[i], id, is_null);
|
||||
|
||||
for (j = 0; j <= vstate->curframe; j++) {
|
||||
state = vstate->frame[j];
|
||||
bpf_for_each_spilled_reg(i, state, reg) {
|
||||
if (!reg)
|
||||
continue;
|
||||
mark_ptr_or_null_reg(state, reg, id, is_null);
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= vstate->curframe; i++)
|
||||
__mark_ptr_or_null_regs(vstate->frame[i], id, is_null);
|
||||
}
|
||||
|
||||
static bool try_match_pkt_pointers(const struct bpf_insn *insn,
|
||||
|
Reference in New Issue
Block a user