@@ -5249,13 +5249,19 @@ static void clear_caller_saved_regs(struct bpf_verifier_env *env,
5249
5249
}
5250
5250
}
5251
5251
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 )
5254
5260
{
5255
5261
struct bpf_verifier_state * state = env -> cur_state ;
5256
5262
struct bpf_func_info_aux * func_info_aux ;
5257
5263
struct bpf_func_state * caller , * callee ;
5258
- int i , err , subprog , target_insn ;
5264
+ int err ;
5259
5265
bool is_global = false;
5260
5266
5261
5267
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,
5264
5270
return - E2BIG ;
5265
5271
}
5266
5272
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
-
5275
5273
caller = state -> frame [state -> curframe ];
5276
5274
if (state -> frame [state -> curframe + 1 ]) {
5277
5275
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,
5326
5324
if (err )
5327
5325
return err ;
5328
5326
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 ;
5334
5330
5335
5331
clear_caller_saved_regs (env , caller -> regs );
5336
5332
5337
5333
/* only increment it after check_reg_arg() finished */
5338
5334
state -> curframe ++ ;
5339
5335
5340
5336
/* and go analyze first insn of the callee */
5341
- * insn_idx = target_insn ;
5337
+ * insn_idx = env -> subprog_info [ subprog ]. start - 1 ;
5342
5338
5343
5339
if (env -> log .level & BPF_LOG_LEVEL ) {
5344
5340
verbose (env , "caller:\n" );
@@ -5349,6 +5345,36 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
5349
5345
return 0 ;
5350
5346
}
5351
5347
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
+
5352
5378
static int prepare_func_exit (struct bpf_verifier_env * env , int * insn_idx )
5353
5379
{
5354
5380
struct bpf_verifier_state * state = env -> cur_state ;
0 commit comments