Skip to content

Commit 679c782

Browse files
ecree-solarflareAlexei Starovoitov
authored andcommitted
bpf/verifier: per-register parent pointers
By giving each register its own liveness chain, we elide the skip_callee() logic. Instead, each register's parent is the state it inherits from; both check_func_call() and prepare_func_exit() automatically connect reg states to the correct chain since when they copy the reg state across (r1-r5 into the callee as args, and r0 out as the return value) they also copy the parent pointer. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 29b5e0f commit 679c782

File tree

2 files changed

+47
-145
lines changed

2 files changed

+47
-145
lines changed

include/linux/bpf_verifier.h

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

4343
struct bpf_reg_state {
44+
/* Ordering of fields matters. See states_equal() */
4445
enum bpf_reg_type type;
4546
union {
4647
/* valid when type == PTR_TO_PACKET */
@@ -59,7 +60,6 @@ struct bpf_reg_state {
5960
* came from, when one is tested for != NULL.
6061
*/
6162
u32 id;
62-
/* Ordering of fields matters. See states_equal() */
6363
/* For scalar types (SCALAR_VALUE), this represents our knowledge of
6464
* the actual value.
6565
* For pointer types, this represents the variable part of the offset
@@ -76,15 +76,15 @@ struct bpf_reg_state {
7676
s64 smax_value; /* maximum possible (s64)value */
7777
u64 umin_value; /* minimum possible (u64)value */
7878
u64 umax_value; /* maximum possible (u64)value */
79+
/* parentage chain for liveness checking */
80+
struct bpf_reg_state *parent;
7981
/* Inside the callee two registers can be both PTR_TO_STACK like
8082
* R1=fp-8 and R2=fp-8, but one of them points to this function stack
8183
* while another to the caller's stack. To differentiate them 'frameno'
8284
* is used which is an index in bpf_verifier_state->frame[] array
8385
* pointing to bpf_func_state.
84-
* This field must be second to last, for states_equal() reasons.
8586
*/
8687
u32 frameno;
87-
/* This field must be last, for states_equal() reasons. */
8888
enum bpf_reg_liveness live;
8989
};
9090

@@ -107,7 +107,6 @@ struct bpf_stack_state {
107107
*/
108108
struct bpf_func_state {
109109
struct bpf_reg_state regs[MAX_BPF_REG];
110-
struct bpf_verifier_state *parent;
111110
/* index of call instruction that called into this func */
112111
int callsite;
113112
/* stack frame number of this function state from pov of
@@ -129,7 +128,6 @@ struct bpf_func_state {
129128
struct bpf_verifier_state {
130129
/* call stack tracking */
131130
struct bpf_func_state *frame[MAX_CALL_FRAMES];
132-
struct bpf_verifier_state *parent;
133131
u32 curframe;
134132
};
135133

kernel/bpf/verifier.c

Lines changed: 44 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,9 @@ static int copy_stack_state(struct bpf_func_state *dst,
380380
/* do_check() starts with zero-sized stack in struct bpf_verifier_state to
381381
* make it consume minimal amount of memory. check_stack_write() access from
382382
* the program calls into realloc_func_state() to grow the stack size.
383-
* Note there is a non-zero 'parent' pointer inside bpf_verifier_state
384-
* which this function copies over. It points to previous bpf_verifier_state
385-
* which is never reallocated
383+
* Note there is a non-zero parent pointer inside each reg of bpf_verifier_state
384+
* which this function copies over. It points to corresponding reg in previous
385+
* bpf_verifier_state which is never reallocated
386386
*/
387387
static int realloc_func_state(struct bpf_func_state *state, int size,
388388
bool copy_old)
@@ -466,7 +466,6 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
466466
dst_state->frame[i] = NULL;
467467
}
468468
dst_state->curframe = src->curframe;
469-
dst_state->parent = src->parent;
470469
for (i = 0; i <= src->curframe; i++) {
471470
dst = dst_state->frame[i];
472471
if (!dst) {
@@ -732,6 +731,7 @@ static void init_reg_state(struct bpf_verifier_env *env,
732731
for (i = 0; i < MAX_BPF_REG; i++) {
733732
mark_reg_not_init(env, regs, i);
734733
regs[i].live = REG_LIVE_NONE;
734+
regs[i].parent = NULL;
735735
}
736736

737737
/* frame pointer */
@@ -876,74 +876,21 @@ static int check_subprogs(struct bpf_verifier_env *env)
876876
return 0;
877877
}
878878

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

934-
if (regno == BPF_REG_FP)
935-
/* We don't need to worry about FP liveness because it's read-only */
936-
return 0;
937-
938888
while (parent) {
939889
/* if read wasn't screened by an earlier write ... */
940-
if (writes && state->frame[state->curframe]->regs[regno].live & REG_LIVE_WRITTEN)
890+
if (writes && state->live & REG_LIVE_WRITTEN)
941891
break;
942-
parent = skip_callee(env, state, parent, regno);
943-
if (!parent)
944-
return -EFAULT;
945892
/* ... then we depend on parent's value */
946-
parent->frame[parent->curframe]->regs[regno].live |= REG_LIVE_READ;
893+
parent->live |= REG_LIVE_READ;
947894
state = parent;
948895
parent = state->parent;
949896
writes = true;
@@ -969,7 +916,10 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
969916
verbose(env, "R%d !read_ok\n", regno);
970917
return -EACCES;
971918
}
972-
return mark_reg_read(env, vstate, vstate->parent, regno);
919+
/* We don't need to worry about FP liveness because it's read-only */
920+
if (regno != BPF_REG_FP)
921+
return mark_reg_read(env, &regs[regno],
922+
regs[regno].parent);
973923
} else {
974924
/* check whether register used as dest operand can be written to */
975925
if (regno == BPF_REG_FP) {
@@ -1080,8 +1030,8 @@ static int check_stack_write(struct bpf_verifier_env *env,
10801030
} else {
10811031
u8 type = STACK_MISC;
10821032

1083-
/* regular write of data into stack */
1084-
state->stack[spi].spilled_ptr = (struct bpf_reg_state) {};
1033+
/* regular write of data into stack destroys any spilled ptr */
1034+
state->stack[spi].spilled_ptr.type = NOT_INIT;
10851035

10861036
/* only mark the slot as written if all 8 bytes were written
10871037
* otherwise read propagation may incorrectly stop too soon
@@ -1106,61 +1056,6 @@ static int check_stack_write(struct bpf_verifier_env *env,
11061056
return 0;
11071057
}
11081058

1109-
/* registers of every function are unique and mark_reg_read() propagates
1110-
* the liveness in the following cases:
1111-
* - from callee into caller for R1 - R5 that were used as arguments
1112-
* - from caller into callee for R0 that used as result of the call
1113-
* - from caller to the same caller skipping states of the callee for R6 - R9,
1114-
* since R6 - R9 are callee saved by implicit function prologue and
1115-
* caller's R6 != callee's R6, so when we propagate liveness up to
1116-
* parent states we need to skip callee states for R6 - R9.
1117-
*
1118-
* stack slot marking is different, since stacks of caller and callee are
1119-
* accessible in both (since caller can pass a pointer to caller's stack to
1120-
* callee which can pass it to another function), hence mark_stack_slot_read()
1121-
* has to propagate the stack liveness to all parent states at given frame number.
1122-
* Consider code:
1123-
* f1() {
1124-
* ptr = fp - 8;
1125-
* *ptr = ctx;
1126-
* call f2 {
1127-
* .. = *ptr;
1128-
* }
1129-
* .. = *ptr;
1130-
* }
1131-
* First *ptr is reading from f1's stack and mark_stack_slot_read() has
1132-
* to mark liveness at the f1's frame and not f2's frame.
1133-
* Second *ptr is also reading from f1's stack and mark_stack_slot_read() has
1134-
* to propagate liveness to f2 states at f1's frame level and further into
1135-
* f1 states at f1's frame level until write into that stack slot
1136-
*/
1137-
static void mark_stack_slot_read(struct bpf_verifier_env *env,
1138-
const struct bpf_verifier_state *state,
1139-
struct bpf_verifier_state *parent,
1140-
int slot, int frameno)
1141-
{
1142-
bool writes = parent == state->parent; /* Observe write marks */
1143-
1144-
while (parent) {
1145-
if (parent->frame[frameno]->allocated_stack <= slot * BPF_REG_SIZE)
1146-
/* since LIVE_WRITTEN mark is only done for full 8-byte
1147-
* write the read marks are conservative and parent
1148-
* state may not even have the stack allocated. In such case
1149-
* end the propagation, since the loop reached beginning
1150-
* of the function
1151-
*/
1152-
break;
1153-
/* if read wasn't screened by an earlier write ... */
1154-
if (writes && state->frame[frameno]->stack[slot].spilled_ptr.live & REG_LIVE_WRITTEN)
1155-
break;
1156-
/* ... then we depend on parent's value */
1157-
parent->frame[frameno]->stack[slot].spilled_ptr.live |= REG_LIVE_READ;
1158-
state = parent;
1159-
parent = state->parent;
1160-
writes = true;
1161-
}
1162-
}
1163-
11641059
static int check_stack_read(struct bpf_verifier_env *env,
11651060
struct bpf_func_state *reg_state /* func where register points to */,
11661061
int off, int size, int value_regno)
@@ -1198,8 +1093,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
11981093
*/
11991094
state->regs[value_regno].live |= REG_LIVE_WRITTEN;
12001095
}
1201-
mark_stack_slot_read(env, vstate, vstate->parent, spi,
1202-
reg_state->frameno);
1096+
mark_reg_read(env, &reg_state->stack[spi].spilled_ptr,
1097+
reg_state->stack[spi].spilled_ptr.parent);
12031098
return 0;
12041099
} else {
12051100
int zeros = 0;
@@ -1215,8 +1110,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
12151110
off, i, size);
12161111
return -EACCES;
12171112
}
1218-
mark_stack_slot_read(env, vstate, vstate->parent, spi,
1219-
reg_state->frameno);
1113+
mark_reg_read(env, &reg_state->stack[spi].spilled_ptr,
1114+
reg_state->stack[spi].spilled_ptr.parent);
12201115
if (value_regno >= 0) {
12211116
if (zeros == size) {
12221117
/* any size read into register is zero extended,
@@ -1908,8 +1803,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
19081803
/* reading any byte out of 8-byte 'spill_slot' will cause
19091804
* the whole slot to be marked as 'read'
19101805
*/
1911-
mark_stack_slot_read(env, env->cur_state, env->cur_state->parent,
1912-
spi, state->frameno);
1806+
mark_reg_read(env, &state->stack[spi].spilled_ptr,
1807+
state->stack[spi].spilled_ptr.parent);
19131808
}
19141809
return update_stack_depth(env, state, off);
19151810
}
@@ -2366,11 +2261,13 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
23662261
state->curframe + 1 /* frameno within this callchain */,
23672262
subprog /* subprog number within this prog */);
23682263

2369-
/* copy r1 - r5 args that callee can access */
2264+
/* copy r1 - r5 args that callee can access. The copy includes parent
2265+
* pointers, which connects us up to the liveness chain
2266+
*/
23702267
for (i = BPF_REG_1; i <= BPF_REG_5; i++)
23712268
callee->regs[i] = caller->regs[i];
23722269

2373-
/* after the call regsiters r0 - r5 were scratched */
2270+
/* after the call registers r0 - r5 were scratched */
23742271
for (i = 0; i < CALLER_SAVED_REGS; i++) {
23752272
mark_reg_not_init(env, caller->regs, caller_saved[i]);
23762273
check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK);
@@ -4370,7 +4267,7 @@ static bool regsafe(struct bpf_reg_state *rold, struct bpf_reg_state *rcur,
43704267
/* explored state didn't use this */
43714268
return true;
43724269

4373-
equal = memcmp(rold, rcur, offsetof(struct bpf_reg_state, frameno)) == 0;
4270+
equal = memcmp(rold, rcur, offsetof(struct bpf_reg_state, parent)) == 0;
43744271

43754272
if (rold->type == PTR_TO_STACK)
43764273
/* two stack pointers are equal only if they're pointing to
@@ -4603,7 +4500,7 @@ static bool states_equal(struct bpf_verifier_env *env,
46034500
* equivalent state (jump target or such) we didn't arrive by the straight-line
46044501
* code, so read marks in the state must propagate to the parent regardless
46054502
* of the state's write marks. That's what 'parent == state->parent' comparison
4606-
* in mark_reg_read() and mark_stack_slot_read() is for.
4503+
* in mark_reg_read() is for.
46074504
*/
46084505
static int propagate_liveness(struct bpf_verifier_env *env,
46094506
const struct bpf_verifier_state *vstate,
@@ -4624,7 +4521,8 @@ static int propagate_liveness(struct bpf_verifier_env *env,
46244521
if (vparent->frame[vparent->curframe]->regs[i].live & REG_LIVE_READ)
46254522
continue;
46264523
if (vstate->frame[vstate->curframe]->regs[i].live & REG_LIVE_READ) {
4627-
err = mark_reg_read(env, vstate, vparent, i);
4524+
err = mark_reg_read(env, &vstate->frame[vstate->curframe]->regs[i],
4525+
&vparent->frame[vstate->curframe]->regs[i]);
46284526
if (err)
46294527
return err;
46304528
}
@@ -4639,7 +4537,8 @@ static int propagate_liveness(struct bpf_verifier_env *env,
46394537
if (parent->stack[i].spilled_ptr.live & REG_LIVE_READ)
46404538
continue;
46414539
if (state->stack[i].spilled_ptr.live & REG_LIVE_READ)
4642-
mark_stack_slot_read(env, vstate, vparent, i, frame);
4540+
mark_reg_read(env, &state->stack[i].spilled_ptr,
4541+
&parent->stack[i].spilled_ptr);
46434542
}
46444543
}
46454544
return err;
@@ -4649,7 +4548,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
46494548
{
46504549
struct bpf_verifier_state_list *new_sl;
46514550
struct bpf_verifier_state_list *sl;
4652-
struct bpf_verifier_state *cur = env->cur_state;
4551+
struct bpf_verifier_state *cur = env->cur_state, *new;
46534552
int i, j, err;
46544553

46554554
sl = env->explored_states[insn_idx];
@@ -4691,16 +4590,18 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
46914590
return -ENOMEM;
46924591

46934592
/* add new state to the head of linked list */
4694-
err = copy_verifier_state(&new_sl->state, cur);
4593+
new = &new_sl->state;
4594+
err = copy_verifier_state(new, cur);
46954595
if (err) {
4696-
free_verifier_state(&new_sl->state, false);
4596+
free_verifier_state(new, false);
46974597
kfree(new_sl);
46984598
return err;
46994599
}
47004600
new_sl->next = env->explored_states[insn_idx];
47014601
env->explored_states[insn_idx] = new_sl;
47024602
/* connect new state to parentage chain */
4703-
cur->parent = &new_sl->state;
4603+
for (i = 0; i < BPF_REG_FP; i++)
4604+
cur_regs(env)[i].parent = &new->frame[new->curframe]->regs[i];
47044605
/* clear write marks in current state: the writes we did are not writes
47054606
* our child did, so they don't screen off its reads from us.
47064607
* (There are no read marks in current state, because reads always mark
@@ -4713,9 +4614,13 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
47134614
/* all stack frames are accessible from callee, clear them all */
47144615
for (j = 0; j <= cur->curframe; j++) {
47154616
struct bpf_func_state *frame = cur->frame[j];
4617+
struct bpf_func_state *newframe = new->frame[j];
47164618

4717-
for (i = 0; i < frame->allocated_stack / BPF_REG_SIZE; i++)
4619+
for (i = 0; i < frame->allocated_stack / BPF_REG_SIZE; i++) {
47184620
frame->stack[i].spilled_ptr.live = REG_LIVE_NONE;
4621+
frame->stack[i].spilled_ptr.parent =
4622+
&newframe->stack[i].spilled_ptr;
4623+
}
47194624
}
47204625
return 0;
47214626
}
@@ -4734,7 +4639,6 @@ static int do_check(struct bpf_verifier_env *env)
47344639
if (!state)
47354640
return -ENOMEM;
47364641
state->curframe = 0;
4737-
state->parent = NULL;
47384642
state->frame[0] = kzalloc(sizeof(struct bpf_func_state), GFP_KERNEL);
47394643
if (!state->frame[0]) {
47404644
kfree(state);

0 commit comments

Comments
 (0)