bpf: Return -EFAULT on misconfigurations
Mark these cases as non-recoverable to later prevent them from being caught when they occur during speculative path verification. Eduard writes [1]: The only pace I'm aware of that might act upon specific error code from verifier syscall is libbpf. Looking through libbpf code, it seems that this change does not interfere with libbpf. [1] https://lore.kernel.org/all/785b4531ce3b44a84059a4feb4ba458c68fce719.camel@gmail.com/ Signed-off-by: Luis Gerhorst <luis.gerhorst@fau.de> Reviewed-by: Eduard Zingerman <eddyz87@gmail.com> Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Acked-by: Henriette Herzog <henriette.herzog@rub.de> Cc: Maximilian Ott <ott@cs.fau.de> Cc: Milan Stephan <milan.stephan@fau.de> Link: https://lore.kernel.org/r/20250603205800.334980-3-luis.gerhorst@fau.de Signed-off-by: Alexei Starovoitov <ast@kernel.org>pull/1309/head
parent
8b7df50fd4
commit
fd508bde5d
|
|
@ -8955,7 +8955,7 @@ static int resolve_map_arg_type(struct bpf_verifier_env *env,
|
||||||
if (!meta->map_ptr) {
|
if (!meta->map_ptr) {
|
||||||
/* kernel subsystem misconfigured verifier */
|
/* kernel subsystem misconfigured verifier */
|
||||||
verbose(env, "invalid map_ptr to access map->type\n");
|
verbose(env, "invalid map_ptr to access map->type\n");
|
||||||
return -EACCES;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (meta->map_ptr->map_type) {
|
switch (meta->map_ptr->map_type) {
|
||||||
|
|
@ -9643,7 +9643,7 @@ skip_type_check:
|
||||||
* that kernel subsystem misconfigured verifier
|
* that kernel subsystem misconfigured verifier
|
||||||
*/
|
*/
|
||||||
verbose(env, "invalid map_ptr to access map->key\n");
|
verbose(env, "invalid map_ptr to access map->key\n");
|
||||||
return -EACCES;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
key_size = meta->map_ptr->key_size;
|
key_size = meta->map_ptr->key_size;
|
||||||
err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL);
|
err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL);
|
||||||
|
|
@ -9670,7 +9670,7 @@ skip_type_check:
|
||||||
if (!meta->map_ptr) {
|
if (!meta->map_ptr) {
|
||||||
/* kernel subsystem misconfigured verifier */
|
/* kernel subsystem misconfigured verifier */
|
||||||
verbose(env, "invalid map_ptr to access map->value\n");
|
verbose(env, "invalid map_ptr to access map->value\n");
|
||||||
return -EACCES;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
meta->raw_mode = arg_type & MEM_UNINIT;
|
meta->raw_mode = arg_type & MEM_UNINIT;
|
||||||
err = check_helper_mem_access(env, regno, meta->map_ptr->value_size,
|
err = check_helper_mem_access(env, regno, meta->map_ptr->value_size,
|
||||||
|
|
@ -10966,7 +10966,7 @@ record_func_map(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
|
||||||
|
|
||||||
if (map == NULL) {
|
if (map == NULL) {
|
||||||
verbose(env, "kernel subsystem misconfigured verifier\n");
|
verbose(env, "kernel subsystem misconfigured verifier\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of read-only, some additional restrictions
|
/* In case of read-only, some additional restrictions
|
||||||
|
|
@ -11005,7 +11005,7 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
|
||||||
return 0;
|
return 0;
|
||||||
if (!map || map->map_type != BPF_MAP_TYPE_PROG_ARRAY) {
|
if (!map || map->map_type != BPF_MAP_TYPE_PROG_ARRAY) {
|
||||||
verbose(env, "kernel subsystem misconfigured verifier\n");
|
verbose(env, "kernel subsystem misconfigured verifier\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg = ®s[BPF_REG_3];
|
reg = ®s[BPF_REG_3];
|
||||||
|
|
@ -11259,7 +11259,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
|
||||||
if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
|
if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
|
||||||
verbose(env, "kernel subsystem misconfigured func %s#%d: r1 != ctx\n",
|
verbose(env, "kernel subsystem misconfigured func %s#%d: r1 != ctx\n",
|
||||||
func_id_name(func_id), func_id);
|
func_id_name(func_id), func_id);
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&meta, 0, sizeof(meta));
|
memset(&meta, 0, sizeof(meta));
|
||||||
|
|
@ -11561,7 +11561,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
|
||||||
if (meta.map_ptr == NULL) {
|
if (meta.map_ptr == NULL) {
|
||||||
verbose(env,
|
verbose(env,
|
||||||
"kernel subsystem misconfigured verifier\n");
|
"kernel subsystem misconfigured verifier\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func_id == BPF_FUNC_map_lookup_elem &&
|
if (func_id == BPF_FUNC_map_lookup_elem &&
|
||||||
|
|
@ -16738,7 +16738,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||||
dst_reg->type = CONST_PTR_TO_MAP;
|
dst_reg->type = CONST_PTR_TO_MAP;
|
||||||
} else {
|
} else {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -16785,7 +16785,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||||
|
|
||||||
if (!env->ops->gen_ld_abs) {
|
if (!env->ops->gen_ld_abs) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insn->dst_reg != BPF_REG_0 || insn->off != 0 ||
|
if (insn->dst_reg != BPF_REG_0 || insn->off != 0 ||
|
||||||
|
|
@ -20825,7 +20825,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
||||||
-(subprogs[0].stack_depth + 8));
|
-(subprogs[0].stack_depth + 8));
|
||||||
if (epilogue_cnt >= INSN_BUF_SIZE) {
|
if (epilogue_cnt >= INSN_BUF_SIZE) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
} else if (epilogue_cnt) {
|
} else if (epilogue_cnt) {
|
||||||
/* Save the ARG_PTR_TO_CTX for the epilogue to use */
|
/* Save the ARG_PTR_TO_CTX for the epilogue to use */
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
|
|
@ -20848,13 +20848,13 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
||||||
if (ops->gen_prologue || env->seen_direct_write) {
|
if (ops->gen_prologue || env->seen_direct_write) {
|
||||||
if (!ops->gen_prologue) {
|
if (!ops->gen_prologue) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
cnt = ops->gen_prologue(insn_buf, env->seen_direct_write,
|
cnt = ops->gen_prologue(insn_buf, env->seen_direct_write,
|
||||||
env->prog);
|
env->prog);
|
||||||
if (cnt >= INSN_BUF_SIZE) {
|
if (cnt >= INSN_BUF_SIZE) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
} else if (cnt) {
|
} else if (cnt) {
|
||||||
new_prog = bpf_patch_insn_data(env, 0, insn_buf, cnt);
|
new_prog = bpf_patch_insn_data(env, 0, insn_buf, cnt);
|
||||||
if (!new_prog)
|
if (!new_prog)
|
||||||
|
|
@ -21011,7 +21011,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
||||||
|
|
||||||
if (type == BPF_WRITE) {
|
if (type == BPF_WRITE) {
|
||||||
verbose(env, "bpf verifier narrow ctx access misconfigured\n");
|
verbose(env, "bpf verifier narrow ctx access misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_code = BPF_H;
|
size_code = BPF_H;
|
||||||
|
|
@ -21030,7 +21030,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
||||||
if (cnt == 0 || cnt >= INSN_BUF_SIZE ||
|
if (cnt == 0 || cnt >= INSN_BUF_SIZE ||
|
||||||
(ctx_field_size && !target_size)) {
|
(ctx_field_size && !target_size)) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_narrower_load && size < target_size) {
|
if (is_narrower_load && size < target_size) {
|
||||||
|
|
@ -21038,7 +21038,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
||||||
off, size, size_default) * 8;
|
off, size, size_default) * 8;
|
||||||
if (shift && cnt + 1 >= INSN_BUF_SIZE) {
|
if (shift && cnt + 1 >= INSN_BUF_SIZE) {
|
||||||
verbose(env, "bpf verifier narrow ctx load misconfigured\n");
|
verbose(env, "bpf verifier narrow ctx load misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
if (ctx_field_size <= 4) {
|
if (ctx_field_size <= 4) {
|
||||||
if (shift)
|
if (shift)
|
||||||
|
|
@ -21803,7 +21803,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
|
||||||
cnt = env->ops->gen_ld_abs(insn, insn_buf);
|
cnt = env->ops->gen_ld_abs(insn, insn_buf);
|
||||||
if (cnt == 0 || cnt >= INSN_BUF_SIZE) {
|
if (cnt == 0 || cnt >= INSN_BUF_SIZE) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
|
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
|
||||||
|
|
@ -22139,7 +22139,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
|
||||||
goto patch_map_ops_generic;
|
goto patch_map_ops_generic;
|
||||||
if (cnt <= 0 || cnt >= INSN_BUF_SIZE) {
|
if (cnt <= 0 || cnt >= INSN_BUF_SIZE) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_prog = bpf_patch_insn_data(env, i + delta,
|
new_prog = bpf_patch_insn_data(env, i + delta,
|
||||||
|
|
@ -22499,7 +22499,7 @@ next_insn:
|
||||||
!map_ptr->ops->map_poke_untrack ||
|
!map_ptr->ops->map_poke_untrack ||
|
||||||
!map_ptr->ops->map_poke_run) {
|
!map_ptr->ops->map_poke_run) {
|
||||||
verbose(env, "bpf verifier is misconfigured\n");
|
verbose(env, "bpf verifier is misconfigured\n");
|
||||||
return -EINVAL;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = map_ptr->ops->map_poke_track(map_ptr, prog->aux);
|
ret = map_ptr->ops->map_poke_track(map_ptr, prog->aux);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue