提交 aae9f312 编写于 作者: D Daniel Borkmann 提交者: Yang Yingliang

bpf: Refactor and streamline bounds check into helper

mainline inclusion
from mainline-v5.12-rc8
commit 073815b7
category: bugfix
bugzilla: NA
CVE: CVE-2021-29155

--------------------------------

Move the bounds check in adjust_ptr_min_max_vals() into a small helper named
sanitize_check_bounds() in order to simplify the former a bit.
Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
Reviewed-by: NJohn Fastabend <john.fastabend@gmail.com>
Acked-by: NAlexei Starovoitov <ast@kernel.org>
Conflicts:
  kernel/bpf/verifier.c
[yyl: bypass_spec_v1 is not introduced in kernel-4.19,
 use allow_ptr_leaks instead]
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Reviewed-by: NKuohai Xu <xukuohai@huawei.com>
Reviewed-by: NXiu Jianfeng <xiujianfeng@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 b331ba02
...@@ -2911,6 +2911,72 @@ static int sanitize_err(struct bpf_verifier_env *env, ...@@ -2911,6 +2911,72 @@ static int sanitize_err(struct bpf_verifier_env *env,
return -EACCES; return -EACCES;
} }
/* check that stack access falls within stack limits and that 'reg' doesn't
* have a variable offset.
*
* Variable offset is prohibited for unprivileged mode for simplicity since it
* requires corresponding support in Spectre masking for stack ALU. See also
* retrieve_ptr_limit().
*
*
* 'off' includes 'reg->off'.
*/
static int check_stack_access_for_ptr_arithmetic(
struct bpf_verifier_env *env,
int regno,
const struct bpf_reg_state *reg,
int off)
{
if (!tnum_is_const(reg->var_off)) {
char tn_buf[48];
tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
verbose(env, "R%d variable stack access prohibited for !root, var_off=%s off=%d\n",
regno, tn_buf, off);
return -EACCES;
}
if (off >= 0 || off < -MAX_BPF_STACK) {
verbose(env, "R%d stack pointer arithmetic goes out of range, "
"prohibited for !root; off=%d\n", regno, off);
return -EACCES;
}
return 0;
}
static int sanitize_check_bounds(struct bpf_verifier_env *env,
const struct bpf_insn *insn,
const struct bpf_reg_state *dst_reg)
{
u32 dst = insn->dst_reg;
/* For unprivileged we require that resulting offset must be in bounds
* in order to be able to sanitize access later on.
*/
if (env->allow_ptr_leaks)
return 0;
switch (dst_reg->type) {
case PTR_TO_STACK:
if (check_stack_access_for_ptr_arithmetic(env, dst, dst_reg,
dst_reg->off + dst_reg->var_off.value))
return -EACCES;
break;
case PTR_TO_MAP_VALUE:
if (check_map_access(env, dst, dst_reg->off, 1, false)) {
verbose(env, "R%d pointer arithmetic of map value goes out of range, "
"prohibited for !root\n", dst);
return -EACCES;
}
break;
default:
break;
}
return 0;
}
/* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off. /* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
* Caller should also handle BPF_MOV case separately. * Caller should also handle BPF_MOV case separately.
* If we return -EACCES, caller may want to try again treating pointer as a * If we return -EACCES, caller may want to try again treating pointer as a
...@@ -3118,24 +3184,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, ...@@ -3118,24 +3184,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
__reg_deduce_bounds(dst_reg); __reg_deduce_bounds(dst_reg);
__reg_bound_offset(dst_reg); __reg_bound_offset(dst_reg);
/* For unprivileged we require that resulting offset must be in bounds
* in order to be able to sanitize access later on.
*/
if (!env->allow_ptr_leaks) {
if (dst_reg->type == PTR_TO_MAP_VALUE &&
check_map_access(env, dst, dst_reg->off, 1, false)) {
verbose(env, "R%d pointer arithmetic of map value goes out of range, "
"prohibited for !root\n", dst);
return -EACCES;
} else if (dst_reg->type == PTR_TO_STACK &&
check_stack_access(env, dst_reg, dst_reg->off +
dst_reg->var_off.value, 1)) {
verbose(env, "R%d stack pointer arithmetic goes out of range, "
"prohibited for !root\n", dst);
return -EACCES;
}
}
if (sanitize_check_bounds(env, insn, dst_reg) < 0)
return -EACCES;
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册