Extract the per-argument FP-derived pointer handling from record_call_access() into a new record_arg_access() helper. The existing loop body — checking arg_is_fp, querying stack access bytes, and calling record_stack_access/record_imprecise — will be reused for stack argument slots in the next patch. Factoring it out now avoids duplicating the logic. No functional change.
Unified · Split
| @@ -1343,6 +1343,42 @@ static int record_load_store_access(struct bpf_verifier_env *env, · 1342 unmodified lines | ||
| 1343 | 1343 | return 0; |
| 1344 | 1344 | } |
| 1345 | 1345 | |
| 1346 | +static int record_arg_access(struct bpf_verifier_env *env, | |
| 1347 | + struct func_instance *instance, | |
| 1348 | + struct bpf_insn *insn, | |
| 1349 | + struct arg_track *at, int arg_idx, | |
| 1350 | + int insn_idx) | |
| 1351 | +{ | |
| 1352 | + int depth = instance->depth; | |
| 1353 | + int frame = at->frame; | |
| 1354 | + int err = 0; | |
| 1355 | + s64 bytes; | |
| 1356 | + | |
| 1357 | + if (!arg_is_fp(at)) | |
| 1358 | + return 0; | |
| 1359 | + | |
| 1360 | + if (bpf_helper_call(insn)) { | |
| 1361 | + bytes = bpf_helper_stack_access_bytes(env, insn, arg_idx, insn_idx); | |
| 1362 | + } else if (bpf_pseudo_kfunc_call(insn)) { | |
| 1363 | + bytes = bpf_kfunc_stack_access_bytes(env, insn, arg_idx, insn_idx); | |
| 1364 | + } else { | |
| 1365 | + for (int f = 0; f <= depth; f++) { | |
| 1366 | + err = mark_stack_read(instance, f, insn_idx, SPIS_ALL); | |
| 1367 | + if (err) | |
| 1368 | + return err; | |
| 1369 | + } | |
| 1370 | + return 0; | |
| 1371 | + } | |
| 1372 | + if (bytes == 0) | |
| 1373 | + return 0; | |
| 1374 | + | |
| 1375 | + if (frame >= 0 && frame <= depth) | |
| 1376 | + err = record_stack_access(instance, at, bytes, frame, insn_idx); | |
| 1377 | + else if (frame == ARG_IMPRECISE) | |
| 1378 | + err = record_imprecise(instance, at->mask, insn_idx); | |
| 1379 | + return err; | |
| 1380 | +} | |
| 1381 | + | |
| 1346 | 1382 | /* Record stack access for a given 'at' state of helper/kfunc 'insn' */ |
| 1347 | 1383 | static int record_call_access(struct bpf_verifier_env *env, |
| 1348 | 1384 | struct func_instance *instance, |
| @@ -1350,9 +1386,8 @@ static int record_call_access(struct bpf_verifier_env *env, · 1 unmodified line | ||
| 1350 | 1386 | int insn_idx) |
| 1351 | 1387 | { |
| 1352 | 1388 | struct bpf_insn *insn = &env->prog->insnsi[insn_idx]; |
| 1353 | − int depth = instance->depth; | |
| 1354 | 1389 | struct bpf_call_summary cs; |
| 1355 | − int r, err = 0, num_params = 5; | |
| 1390 | + int r, err, num_params = 5; | |
| 1356 | 1391 | |
| 1357 | 1392 | if (bpf_pseudo_call(insn)) |
| 1358 | 1393 | return 0; |
| @@ -1361,31 +1396,7 @@ static int record_call_access(struct bpf_verifier_env *env, · 2 unmodified lines | ||
| 1361 | 1396 | num_params = cs.num_params; |
| 1362 | 1397 | |
| 1363 | 1398 | for (r = BPF_REG_1; r < BPF_REG_1 + num_params; r++) { |
| 1364 | − int frame = at[r].frame; | |
| 1365 | − s64 bytes; | |
| 1366 | − | |
| 1367 | − if (!arg_is_fp(&at[r])) | |
| 1368 | − continue; | |
| 1369 | − | |
| 1370 | − if (bpf_helper_call(insn)) { | |
| 1371 | − bytes = bpf_helper_stack_access_bytes(env, insn, r - 1, insn_idx); | |
| 1372 | − } else if (bpf_pseudo_kfunc_call(insn)) { | |
| 1373 | − bytes = bpf_kfunc_stack_access_bytes(env, insn, r - 1, insn_idx); | |
| 1374 | − } else { | |
| 1375 | − for (int f = 0; f <= depth; f++) { | |
| 1376 | − err = mark_stack_read(instance, f, insn_idx, SPIS_ALL); | |
| 1377 | − if (err) | |
| 1378 | − return err; | |
| 1379 | − } | |
| 1380 | − return 0; | |
| 1381 | − } | |
| 1382 | − if (bytes == 0) | |
| 1383 | − continue; | |
| 1384 | − | |
| 1385 | − if (frame >= 0 && frame <= depth) | |
| 1386 | − err = record_stack_access(instance, &at[r], bytes, frame, insn_idx); | |
| 1387 | − else if (frame == ARG_IMPRECISE) | |
| 1388 | − err = record_imprecise(instance, at[r].mask, insn_idx); | |
| 1399 | + err = record_arg_access(env, instance, insn, &at[r], r - 1, insn_idx); | |
| 1389 | 1400 | if (err) |
| 1390 | 1401 | return err; |
| 1391 | 1402 | } |