mirror of
https://github.com/torvalds/linux.git
synced 2026-09-28 03:52:02 +02:00
bpf: Apply CO-RE relocations before subprogram validation
check_subprogs() verifies that each subprogram ends in an exit or an
unconditional jump before in-kernel CO-RE relocations are applied. An
unresolved relocation can then replace that terminal instruction with an
invalid helper call. The resulting fall-through into another subprogram
breaks the CFG invariant used by postorder and stack liveness analysis,
which can write past their per-subprogram arrays.
Apply CO-RE relocations immediately after preparing the program BTF, before
subprogram discovery and validation. Keep func_info and line_info validation
after subprogram discovery because those records depend on the complete
subprogram layout.
Reject an ldimm64 first slot at the end of the instruction stream before
CO-RE can inspect its missing second slot. check_subprogs() previously
rejected this form before relocation processing because it is not a valid
subprogram terminator. Moving CO-RE ahead of check_subprogs() removes that
implicit protection, so perform an explicit check before applying
relocations.
Include core_relo_cnt when deciding whether to prepare program BTF. A load
that supplied only CO-RE relocation metadata previously skipped both BTF
setup and relocation processing.
Fixes: fbd94c7afc ("bpf: Pass a set of bpf_core_relo-s to prog_load command.")
Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260917233222.2542500-5-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
This commit is contained in:
parent
2059d9af54
commit
c26e97721b
|
|
@ -1197,6 +1197,8 @@ static inline void bpf_trampoline_unpack_key(u64 key, u32 *obj_id, u32 *btf_id)
|
|||
|
||||
int bpf_prepare_btf_info(struct bpf_verifier_env *env,
|
||||
const union bpf_attr *attr, bpfptr_t uattr);
|
||||
int bpf_check_core_relo(struct bpf_verifier_env *env,
|
||||
const union bpf_attr *attr, bpfptr_t uattr);
|
||||
int bpf_check_btf_info(struct bpf_verifier_env *env,
|
||||
const union bpf_attr *attr, bpfptr_t uattr);
|
||||
|
||||
|
|
|
|||
|
|
@ -338,9 +338,9 @@ static int check_btf_line(struct bpf_verifier_env *env,
|
|||
#define MIN_CORE_RELO_SIZE sizeof(struct bpf_core_relo)
|
||||
#define MAX_CORE_RELO_SIZE MAX_FUNCINFO_REC_SIZE
|
||||
|
||||
static int check_core_relo(struct bpf_verifier_env *env,
|
||||
const union bpf_attr *attr,
|
||||
bpfptr_t uattr)
|
||||
int bpf_check_core_relo(struct bpf_verifier_env *env,
|
||||
const union bpf_attr *attr,
|
||||
bpfptr_t uattr)
|
||||
{
|
||||
u32 i, nr_core_relo, ncopy, expected_size, rec_size;
|
||||
struct bpf_core_relo core_relo = {};
|
||||
|
|
@ -414,7 +414,7 @@ int bpf_prepare_btf_info(struct bpf_verifier_env *env,
|
|||
struct btf *btf;
|
||||
int err;
|
||||
|
||||
if (!attr->func_info_cnt && !attr->line_info_cnt) {
|
||||
if (!attr->func_info_cnt && !attr->line_info_cnt && !attr->core_relo_cnt) {
|
||||
if (check_abnormal_return(env))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
|
@ -455,9 +455,5 @@ int bpf_check_btf_info(struct bpf_verifier_env *env,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = check_core_relo(env, attr, uattr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21199,6 +21199,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
|
|||
ret = bpf_diag_init(env);
|
||||
if (ret)
|
||||
goto err_prep;
|
||||
if (env->prog->insnsi[env->prog->len - 1].code == (BPF_LD | BPF_IMM | BPF_DW)) {
|
||||
verbose(env, "invalid bpf_ld_imm64 insn\n");
|
||||
ret = -EINVAL;
|
||||
goto err_prep;
|
||||
}
|
||||
if (env->signature) {
|
||||
ret = bpf_prog_calc_tag(env->prog);
|
||||
if (ret < 0)
|
||||
|
|
@ -21274,6 +21279,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
|
|||
if (ret < 0)
|
||||
goto skip_full_check;
|
||||
|
||||
/* Apply CO-RE before validating the program's instruction layout. */
|
||||
ret = bpf_check_core_relo(env, attr, uattr);
|
||||
if (ret < 0)
|
||||
goto skip_full_check;
|
||||
|
||||
/* Discover all subprograms before validating their layout and BTF. */
|
||||
ret = add_subprogs(env);
|
||||
if (ret < 0)
|
||||
|
|
@ -21283,7 +21293,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
|
|||
if (ret < 0)
|
||||
goto skip_full_check;
|
||||
|
||||
/* Validate BTF against the complete subprogram layout and apply CO-RE. */
|
||||
/* Validate BTF against the complete subprogram layout. */
|
||||
ret = bpf_check_btf_info(env, attr, uattr);
|
||||
if (ret < 0)
|
||||
goto skip_full_check;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user