Skip to content

Commit e9e614c

Browse files
shiloongmaqiao-mq
authored andcommitted
Revert "bpf/verifier: per-register parent pointers"
ANBZ: torvalds#342 This reverts commit 4c01b7f. Signed-off-by: Qiao Ma <[email protected]> Acked-by: Mao Wenan <[email protected]> Acked-by: Tony Lu <[email protected]>
1 parent 825ad97 commit e9e614c

File tree

2 files changed

+144
-47
lines changed

2 files changed

+144
-47
lines changed

include/linux/bpf_verifier.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ enum bpf_reg_liveness {
4141
};
4242

4343
struct bpf_reg_state {
44-
/* Ordering of fields matters. See states_equal() */
4544
enum bpf_reg_type type;
4645
union {
4746
/* valid when type == PTR_TO_PACKET */
@@ -63,6 +62,7 @@ struct bpf_reg_state {
6362
* came from, when one is tested for != NULL.
6463
*/
6564
u32 id;
65+
/* Ordering of fields matters. See states_equal() */
6666
/* For scalar types (SCALAR_VALUE), this represents our knowledge of
6767
* the actual value.
6868
* For pointer types, this represents the variable part of the offset
@@ -79,15 +79,15 @@ struct bpf_reg_state {
7979
s64 smax_value; /* maximum possible (s64)value */
8080
u64 umin_value; /* minimum possible (u64)value */
8181
u64 umax_value; /* maximum possible (u64)value */
82-
/* parentage chain for liveness checking */
83-
struct bpf_reg_state *parent;
8482
/* Inside the callee two registers can be both PTR_TO_STACK like
8583
* R1=fp-8 and R2=fp-8, but one of them points to this function stack
8684
* while another to the caller's stack. To differentiate them 'frameno'
8785
* is used which is an index in bpf_verifier_state->frame[] array
8886
* pointing to bpf_func_state.
87+
* This field must be second to last, for states_equal() reasons.
8988
*/
9089
u32 frameno;
90+
/* This field must be last, for states_equal() reasons. */
9191
enum bpf_reg_liveness live;
9292
};
9393

@@ -110,6 +110,7 @@ struct bpf_stack_state {
110110
*/
111111
struct bpf_func_state {
112112
struct bpf_reg_state regs[MAX_BPF_REG];
113+
struct bpf_verifier_state *parent;
113114
/* index of call instruction that called into this func */
114115
int callsite;
115116
/* stack frame number of this function state from pov of
@@ -131,6 +132,7 @@ struct bpf_func_state {
131132
struct bpf_verifier_state {
132133
/* call stack tracking */
133134
struct bpf_func_state *frame[MAX_CALL_FRAMES];
135+
struct bpf_verifier_state *parent;
134136
u32 curframe;
135137
bool speculative;
136138
};

kernel/bpf/verifier.c

Lines changed: 139 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,9 @@ static int copy_stack_state(struct bpf_func_state *dst,
381381
/* do_check() starts with zero-sized stack in struct bpf_verifier_state to
382382
* make it consume minimal amount of memory. check_stack_write() access from
383383
* the program calls into realloc_func_state() to grow the stack size.
384-
* Note there is a non-zero parent pointer inside each reg of bpf_verifier_state
385-
* which this function copies over. It points to corresponding reg in previous
386-
* bpf_verifier_state which is never reallocated
384+
* Note there is a non-zero 'parent' pointer inside bpf_verifier_state
385+
* which this function copies over. It points to previous bpf_verifier_state
386+
* which is never reallocated
387387
*/
388388
static int realloc_func_state(struct bpf_func_state *state, int size,
389389
bool copy_old)
@@ -468,6 +468,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
468468
}
469469
dst_state->speculative = src->speculative;
470470
dst_state->curframe = src->curframe;
471+
dst_state->parent = src->parent;
471472
for (i = 0; i <= src->curframe; i++) {
472473
dst = dst_state->frame[i];
473474
if (!dst) {
@@ -739,7 +740,6 @@ static void init_reg_state(struct bpf_verifier_env *env,
739740
for (i = 0; i < MAX_BPF_REG; i++) {
740741
mark_reg_not_init(env, regs, i);
741742
regs[i].live = REG_LIVE_NONE;
742-
regs[i].parent = NULL;
743743
}
744744

745745
/* frame pointer */
@@ -884,21 +884,74 @@ static int check_subprogs(struct bpf_verifier_env *env)
884884
return 0;
885885
}
886886

887-
/* Parentage chain of this register (or stack slot) should take care of all
888-
* issues like callee-saved registers, stack slot allocation time, etc.
889-
*/
887+
static
888+
struct bpf_verifier_state *skip_callee(struct bpf_verifier_env *env,
889+
const struct bpf_verifier_state *state,
890+
struct bpf_verifier_state *parent,
891+
u32 regno)
892+
{
893+
struct bpf_verifier_state *tmp = NULL;
894+
895+
/* 'parent' could be a state of caller and
896+
* 'state' could be a state of callee. In such case
897+
* parent->curframe < state->curframe
898+
* and it's ok for r1 - r5 registers
899+
*
900+
* 'parent' could be a callee's state after it bpf_exit-ed.
901+
* In such case parent->curframe > state->curframe
902+
* and it's ok for r0 only
903+
*/
904+
if (parent->curframe == state->curframe ||
905+
(parent->curframe < state->curframe &&
906+
regno >= BPF_REG_1 && regno <= BPF_REG_5) ||
907+
(parent->curframe > state->curframe &&
908+
regno == BPF_REG_0))
909+
return parent;
910+
911+
if (parent->curframe > state->curframe &&
912+
regno >= BPF_REG_6) {
913+
/* for callee saved regs we have to skip the whole chain
914+
* of states that belong to callee and mark as LIVE_READ
915+
* the registers before the call
916+
*/
917+
tmp = parent;
918+
while (tmp && tmp->curframe != state->curframe) {
919+
tmp = tmp->parent;
920+
}
921+
if (!tmp)
922+
goto bug;
923+
parent = tmp;
924+
} else {
925+
goto bug;
926+
}
927+
return parent;
928+
bug:
929+
verbose(env, "verifier bug regno %d tmp %p\n", regno, tmp);
930+
verbose(env, "regno %d parent frame %d current frame %d\n",
931+
regno, parent->curframe, state->curframe);
932+
return NULL;
933+
}
934+
890935
static int mark_reg_read(struct bpf_verifier_env *env,
891-
const struct bpf_reg_state *state,
892-
struct bpf_reg_state *parent)
936+
const struct bpf_verifier_state *state,
937+
struct bpf_verifier_state *parent,
938+
u32 regno)
893939
{
894940
bool writes = parent == state->parent; /* Observe write marks */
895941

942+
if (regno == BPF_REG_FP)
943+
/* We don't need to worry about FP liveness because it's read-only */
944+
return 0;
945+
896946
while (parent) {
897947
/* if read wasn't screened by an earlier write ... */
898-
if (writes && state->live & REG_LIVE_WRITTEN)
948+
if (writes && state->frame[state->curframe]->regs[regno].live & REG_LIVE_WRITTEN)
899949
break;
950+
parent = skip_callee(env, state, parent, regno);
951+
if (!parent)
952+
return -EFAULT;
900953
/* ... then we depend on parent's value */
901-
parent->live |= REG_LIVE_READ;
954+
parent->frame[parent->curframe]->regs[regno].live |= REG_LIVE_READ;
902955
state = parent;
903956
parent = state->parent;
904957
writes = true;
@@ -924,10 +977,7 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
924977
verbose(env, "R%d !read_ok\n", regno);
925978
return -EACCES;
926979
}
927-
/* We don't need to worry about FP liveness because it's read-only */
928-
if (regno != BPF_REG_FP)
929-
return mark_reg_read(env, &regs[regno],
930-
regs[regno].parent);
980+
return mark_reg_read(env, vstate, vstate->parent, regno);
931981
} else {
932982
/* check whether register used as dest operand can be written to */
933983
if (regno == BPF_REG_FP) {
@@ -1038,8 +1088,8 @@ static int check_stack_write(struct bpf_verifier_env *env,
10381088
} else {
10391089
u8 type = STACK_MISC;
10401090

1041-
/* regular write of data into stack destroys any spilled ptr */
1042-
state->stack[spi].spilled_ptr.type = NOT_INIT;
1091+
/* regular write of data into stack */
1092+
state->stack[spi].spilled_ptr = (struct bpf_reg_state) {};
10431093

10441094
/* only mark the slot as written if all 8 bytes were written
10451095
* otherwise read propagation may incorrectly stop too soon
@@ -1064,6 +1114,61 @@ static int check_stack_write(struct bpf_verifier_env *env,
10641114
return 0;
10651115
}
10661116

1117+
/* registers of every function are unique and mark_reg_read() propagates
1118+
* the liveness in the following cases:
1119+
* - from callee into caller for R1 - R5 that were used as arguments
1120+
* - from caller into callee for R0 that used as result of the call
1121+
* - from caller to the same caller skipping states of the callee for R6 - R9,
1122+
* since R6 - R9 are callee saved by implicit function prologue and
1123+
* caller's R6 != callee's R6, so when we propagate liveness up to
1124+
* parent states we need to skip callee states for R6 - R9.
1125+
*
1126+
* stack slot marking is different, since stacks of caller and callee are
1127+
* accessible in both (since caller can pass a pointer to caller's stack to
1128+
* callee which can pass it to another function), hence mark_stack_slot_read()
1129+
* has to propagate the stack liveness to all parent states at given frame number.
1130+
* Consider code:
1131+
* f1() {
1132+
* ptr = fp - 8;
1133+
* *ptr = ctx;
1134+
* call f2 {
1135+
* .. = *ptr;
1136+
* }
1137+
* .. = *ptr;
1138+
* }
1139+
* First *ptr is reading from f1's stack and mark_stack_slot_read() has
1140+
* to mark liveness at the f1's frame and not f2's frame.
1141+
* Second *ptr is also reading from f1's stack and mark_stack_slot_read() has
1142+
* to propagate liveness to f2 states at f1's frame level and further into
1143+
* f1 states at f1's frame level until write into that stack slot
1144+
*/
1145+
static void mark_stack_slot_read(struct bpf_verifier_env *env,
1146+
const struct bpf_verifier_state *state,
1147+
struct bpf_verifier_state *parent,
1148+
int slot, int frameno)
1149+
{
1150+
bool writes = parent == state->parent; /* Observe write marks */
1151+
1152+
while (parent) {
1153+
if (parent->frame[frameno]->allocated_stack <= slot * BPF_REG_SIZE)
1154+
/* since LIVE_WRITTEN mark is only done for full 8-byte
1155+
* write the read marks are conservative and parent
1156+
* state may not even have the stack allocated. In such case
1157+
* end the propagation, since the loop reached beginning
1158+
* of the function
1159+
*/
1160+
break;
1161+
/* if read wasn't screened by an earlier write ... */
1162+
if (writes && state->frame[frameno]->stack[slot].spilled_ptr.live & REG_LIVE_WRITTEN)
1163+
break;
1164+
/* ... then we depend on parent's value */
1165+
parent->frame[frameno]->stack[slot].spilled_ptr.live |= REG_LIVE_READ;
1166+
state = parent;
1167+
parent = state->parent;
1168+
writes = true;
1169+
}
1170+
}
1171+
10671172
static int check_stack_read(struct bpf_verifier_env *env,
10681173
struct bpf_func_state *reg_state /* func where register points to */,
10691174
int off, int size, int value_regno)
@@ -1101,8 +1206,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
11011206
*/
11021207
state->regs[value_regno].live |= REG_LIVE_WRITTEN;
11031208
}
1104-
mark_reg_read(env, &reg_state->stack[spi].spilled_ptr,
1105-
reg_state->stack[spi].spilled_ptr.parent);
1209+
mark_stack_slot_read(env, vstate, vstate->parent, spi,
1210+
reg_state->frameno);
11061211
return 0;
11071212
} else {
11081213
int zeros = 0;
@@ -1118,8 +1223,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
11181223
off, i, size);
11191224
return -EACCES;
11201225
}
1121-
mark_reg_read(env, &reg_state->stack[spi].spilled_ptr,
1122-
reg_state->stack[spi].spilled_ptr.parent);
1226+
mark_stack_slot_read(env, vstate, vstate->parent, spi,
1227+
reg_state->frameno);
11231228
if (value_regno >= 0) {
11241229
if (zeros == size) {
11251230
/* any size read into register is zero extended,
@@ -1823,8 +1928,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
18231928
/* reading any byte out of 8-byte 'spill_slot' will cause
18241929
* the whole slot to be marked as 'read'
18251930
*/
1826-
mark_reg_read(env, &state->stack[spi].spilled_ptr,
1827-
state->stack[spi].spilled_ptr.parent);
1931+
mark_stack_slot_read(env, env->cur_state, env->cur_state->parent,
1932+
spi, state->frameno);
18281933
}
18291934
return update_stack_depth(env, state, off);
18301935
}
@@ -2281,13 +2386,11 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
22812386
state->curframe + 1 /* frameno within this callchain */,
22822387
subprog /* subprog number within this prog */);
22832388

2284-
/* copy r1 - r5 args that callee can access. The copy includes parent
2285-
* pointers, which connects us up to the liveness chain
2286-
*/
2389+
/* copy r1 - r5 args that callee can access */
22872390
for (i = BPF_REG_1; i <= BPF_REG_5; i++)
22882391
callee->regs[i] = caller->regs[i];
22892392

2290-
/* after the call registers r0 - r5 were scratched */
2393+
/* after the call regsiters r0 - r5 were scratched */
22912394
for (i = 0; i < CALLER_SAVED_REGS; i++) {
22922395
mark_reg_not_init(env, caller->regs, caller_saved[i]);
22932396
check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK);
@@ -4706,7 +4809,7 @@ static bool regsafe(struct bpf_reg_state *rold, struct bpf_reg_state *rcur,
47064809
/* explored state didn't use this */
47074810
return true;
47084811

4709-
equal = memcmp(rold, rcur, offsetof(struct bpf_reg_state, parent)) == 0;
4812+
equal = memcmp(rold, rcur, offsetof(struct bpf_reg_state, frameno)) == 0;
47104813

47114814
if (rold->type == PTR_TO_STACK)
47124815
/* two stack pointers are equal only if they're pointing to
@@ -4945,7 +5048,7 @@ static bool states_equal(struct bpf_verifier_env *env,
49455048
* equivalent state (jump target or such) we didn't arrive by the straight-line
49465049
* code, so read marks in the state must propagate to the parent regardless
49475050
* of the state's write marks. That's what 'parent == state->parent' comparison
4948-
* in mark_reg_read() is for.
5051+
* in mark_reg_read() and mark_stack_slot_read() is for.
49495052
*/
49505053
static int propagate_liveness(struct bpf_verifier_env *env,
49515054
const struct bpf_verifier_state *vstate,
@@ -4966,8 +5069,7 @@ static int propagate_liveness(struct bpf_verifier_env *env,
49665069
if (vparent->frame[vparent->curframe]->regs[i].live & REG_LIVE_READ)
49675070
continue;
49685071
if (vstate->frame[vstate->curframe]->regs[i].live & REG_LIVE_READ) {
4969-
err = mark_reg_read(env, &vstate->frame[vstate->curframe]->regs[i],
4970-
&vparent->frame[vstate->curframe]->regs[i]);
5072+
err = mark_reg_read(env, vstate, vparent, i);
49715073
if (err)
49725074
return err;
49735075
}
@@ -4982,8 +5084,7 @@ static int propagate_liveness(struct bpf_verifier_env *env,
49825084
if (parent->stack[i].spilled_ptr.live & REG_LIVE_READ)
49835085
continue;
49845086
if (state->stack[i].spilled_ptr.live & REG_LIVE_READ)
4985-
mark_reg_read(env, &state->stack[i].spilled_ptr,
4986-
&parent->stack[i].spilled_ptr);
5087+
mark_stack_slot_read(env, vstate, vparent, i, frame);
49875088
}
49885089
}
49895090
return err;
@@ -4993,7 +5094,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
49935094
{
49945095
struct bpf_verifier_state_list *new_sl;
49955096
struct bpf_verifier_state_list *sl;
4996-
struct bpf_verifier_state *cur = env->cur_state, *new;
5097+
struct bpf_verifier_state *cur = env->cur_state;
49975098
int i, j, err, states_cnt = 0;
49985099

49995100
sl = env->explored_states[insn_idx];
@@ -5039,18 +5140,16 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
50395140
return -ENOMEM;
50405141

50415142
/* add new state to the head of linked list */
5042-
new = &new_sl->state;
5043-
err = copy_verifier_state(new, cur);
5143+
err = copy_verifier_state(&new_sl->state, cur);
50445144
if (err) {
5045-
free_verifier_state(new, false);
5145+
free_verifier_state(&new_sl->state, false);
50465146
kfree(new_sl);
50475147
return err;
50485148
}
50495149
new_sl->next = env->explored_states[insn_idx];
50505150
env->explored_states[insn_idx] = new_sl;
50515151
/* connect new state to parentage chain */
5052-
for (i = 0; i < BPF_REG_FP; i++)
5053-
cur_regs(env)[i].parent = &new->frame[new->curframe]->regs[i];
5152+
cur->parent = &new_sl->state;
50545153
/* clear write marks in current state: the writes we did are not writes
50555154
* our child did, so they don't screen off its reads from us.
50565155
* (There are no read marks in current state, because reads always mark
@@ -5063,13 +5162,9 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
50635162
/* all stack frames are accessible from callee, clear them all */
50645163
for (j = 0; j <= cur->curframe; j++) {
50655164
struct bpf_func_state *frame = cur->frame[j];
5066-
struct bpf_func_state *newframe = new->frame[j];
50675165

5068-
for (i = 0; i < frame->allocated_stack / BPF_REG_SIZE; i++) {
5166+
for (i = 0; i < frame->allocated_stack / BPF_REG_SIZE; i++)
50695167
frame->stack[i].spilled_ptr.live = REG_LIVE_NONE;
5070-
frame->stack[i].spilled_ptr.parent =
5071-
&newframe->stack[i].spilled_ptr;
5072-
}
50735168
}
50745169
return 0;
50755170
}

0 commit comments

Comments
 (0)