mirror of
https://gitee.com/openharmony/kernel_linux
synced 2025-04-15 05:43:05 +00:00
bpf: extend is_branch_taken to registers
stable inclusion from linux-4.19.193 commit e0b86677fb3e4622b444dcdd8546caa0dba8a689 category: bugfix issue: #I42H19 CVE: NA -------------------------------- commit fb8d251ee2a6bf4d7f4af5548e9c8f4fb5f90402 upstream This patch extends is_branch_taken() logic from JMP+K instructions to JMP+X instructions. Conditional branches are often done when src and dst registers contain known scalars. In such case the verifier can follow the branch that is going to be taken when program executes. That speeds up the verification and is essential feature to support bounded loops. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> [OP: drop is_jmp32 parameter from is_branch_taken() calls and adjust context] Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Signed-off-by: Yu Changchun <yuchangchun1@huawei.com>
This commit is contained in:
parent
6b618f134e
commit
1b19c0c5e0
@ -4391,9 +4391,10 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
struct bpf_verifier_state *this_branch = env->cur_state;
|
||||
struct bpf_verifier_state *other_branch;
|
||||
struct bpf_reg_state *regs = this_branch->frame[this_branch->curframe]->regs;
|
||||
struct bpf_reg_state *dst_reg, *other_branch_regs;
|
||||
struct bpf_reg_state *dst_reg, *other_branch_regs, *src_reg = NULL;
|
||||
u8 opcode = BPF_OP(insn->code);
|
||||
bool is_jmp32;
|
||||
int pred = -1;
|
||||
int err;
|
||||
|
||||
/* Only conditional jumps are expected to reach here. */
|
||||
@ -4418,6 +4419,7 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
insn->src_reg);
|
||||
return -EACCES;
|
||||
}
|
||||
src_reg = ®s[insn->src_reg];
|
||||
} else {
|
||||
if (insn->src_reg != BPF_REG_0) {
|
||||
verbose(env, "BPF_JMP/JMP32 uses reserved fields\n");
|
||||
@ -4433,20 +4435,21 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
dst_reg = ®s[insn->dst_reg];
|
||||
is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
|
||||
|
||||
if (BPF_SRC(insn->code) == BPF_K) {
|
||||
int pred = is_branch_taken(dst_reg, insn->imm, opcode,
|
||||
is_jmp32);
|
||||
|
||||
if (pred == 1) {
|
||||
/* only follow the goto, ignore fall-through */
|
||||
*insn_idx += insn->off;
|
||||
return 0;
|
||||
} else if (pred == 0) {
|
||||
/* only follow fall-through branch, since
|
||||
* that's where the program will go
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (BPF_SRC(insn->code) == BPF_K)
|
||||
pred = is_branch_taken(dst_reg, insn->imm, opcode, is_jmp32);
|
||||
else if (src_reg->type == SCALAR_VALUE &&
|
||||
tnum_is_const(src_reg->var_off))
|
||||
pred = is_branch_taken(dst_reg, src_reg->var_off.value,
|
||||
opcode, is_jmp32);
|
||||
if (pred == 1) {
|
||||
/* only follow the goto, ignore fall-through */
|
||||
*insn_idx += insn->off;
|
||||
return 0;
|
||||
} else if (pred == 0) {
|
||||
/* only follow fall-through branch, since
|
||||
* that's where the program will go
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
other_branch = push_stack(env, *insn_idx + insn->off + 1, *insn_idx,
|
||||
|
Loading…
x
Reference in New Issue
Block a user