@@ -5249,13 +5249,19 @@ static void clear_caller_saved_regs(struct bpf_verifier_env *env,
52495249 }
52505250}
52515251
5252- static int check_func_call (struct bpf_verifier_env * env , struct bpf_insn * insn ,
5253- int * insn_idx )
5252+ typedef int (* set_callee_state_fn )(struct bpf_verifier_env * env ,
5253+ struct bpf_func_state * caller ,
5254+ struct bpf_func_state * callee ,
5255+ int insn_idx );
5256+
5257+ static int __check_func_call (struct bpf_verifier_env * env , struct bpf_insn * insn ,
5258+ int * insn_idx , int subprog ,
5259+ set_callee_state_fn set_callee_state_cb )
52545260{
52555261 struct bpf_verifier_state * state = env -> cur_state ;
52565262 struct bpf_func_info_aux * func_info_aux ;
52575263 struct bpf_func_state * caller , * callee ;
5258- int i , err , subprog , target_insn ;
5264+ int err ;
52595265 bool is_global = false;
52605266
52615267 if (state -> curframe + 1 >= MAX_CALL_FRAMES ) {
@@ -5264,14 +5270,6 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
52645270 return - E2BIG ;
52655271 }
52665272
5267- target_insn = * insn_idx + insn -> imm ;
5268- subprog = find_subprog (env , target_insn + 1 );
5269- if (subprog < 0 ) {
5270- verbose (env , "verifier bug. No program starts at insn %d\n" ,
5271- target_insn + 1 );
5272- return - EFAULT ;
5273- }
5274-
52755273 caller = state -> frame [state -> curframe ];
52765274 if (state -> frame [state -> curframe + 1 ]) {
52775275 verbose (env , "verifier bug. Frame %d already allocated\n" ,
@@ -5326,19 +5324,17 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
53265324 if (err )
53275325 return err ;
53285326
5329- /* copy r1 - r5 args that callee can access. The copy includes parent
5330- * pointers, which connects us up to the liveness chain
5331- */
5332- for (i = BPF_REG_1 ; i <= BPF_REG_5 ; i ++ )
5333- callee -> regs [i ] = caller -> regs [i ];
5327+ err = set_callee_state_cb (env , caller , callee , * insn_idx );
5328+ if (err )
5329+ return err ;
53345330
53355331 clear_caller_saved_regs (env , caller -> regs );
53365332
53375333 /* only increment it after check_reg_arg() finished */
53385334 state -> curframe ++ ;
53395335
53405336 /* and go analyze first insn of the callee */
5341- * insn_idx = target_insn ;
5337+ * insn_idx = env -> subprog_info [ subprog ]. start - 1 ;
53425338
53435339 if (env -> log .level & BPF_LOG_LEVEL ) {
53445340 verbose (env , "caller:\n" );
@@ -5349,6 +5345,36 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
53495345 return 0 ;
53505346}
53515347
5348+ static int set_callee_state (struct bpf_verifier_env * env ,
5349+ struct bpf_func_state * caller ,
5350+ struct bpf_func_state * callee , int insn_idx )
5351+ {
5352+ int i ;
5353+
5354+ /* copy r1 - r5 args that callee can access. The copy includes parent
5355+ * pointers, which connects us up to the liveness chain
5356+ */
5357+ for (i = BPF_REG_1 ; i <= BPF_REG_5 ; i ++ )
5358+ callee -> regs [i ] = caller -> regs [i ];
5359+ return 0 ;
5360+ }
5361+
5362+ static int check_func_call (struct bpf_verifier_env * env , struct bpf_insn * insn ,
5363+ int * insn_idx )
5364+ {
5365+ int subprog , target_insn ;
5366+
5367+ target_insn = * insn_idx + insn -> imm + 1 ;
5368+ subprog = find_subprog (env , target_insn );
5369+ if (subprog < 0 ) {
5370+ verbose (env , "verifier bug. No program starts at insn %d\n" ,
5371+ target_insn );
5372+ return - EFAULT ;
5373+ }
5374+
5375+ return __check_func_call (env , insn , insn_idx , subprog , set_callee_state );
5376+ }
5377+
53525378static int prepare_func_exit (struct bpf_verifier_env * env , int * insn_idx )
53535379{
53545380 struct bpf_verifier_state * state = env -> cur_state ;
0 commit comments