mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
Revert "bpf: decouple prune and jump points"
This reverts commit743f3548d3which is commitbffdeaa8a5upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: If00d7f3353d6d173c93006a76d575194c7e4f517 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -430,7 +430,6 @@ struct bpf_insn_aux_data {
|
|||||||
/* below fields are initialized once */
|
/* below fields are initialized once */
|
||||||
unsigned int orig_idx; /* original instruction index */
|
unsigned int orig_idx; /* original instruction index */
|
||||||
bool prune_point;
|
bool prune_point;
|
||||||
bool jmp_point;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
|
#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
|
||||||
|
|||||||
@@ -2512,16 +2512,6 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_jmp_point(struct bpf_verifier_env *env, int idx)
|
|
||||||
{
|
|
||||||
env->insn_aux_data[idx].jmp_point = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_jmp_point(struct bpf_verifier_env *env, int insn_idx)
|
|
||||||
{
|
|
||||||
return env->insn_aux_data[insn_idx].jmp_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for any branch, call, exit record the history of jmps in the given state */
|
/* for any branch, call, exit record the history of jmps in the given state */
|
||||||
static int push_jmp_history(struct bpf_verifier_env *env,
|
static int push_jmp_history(struct bpf_verifier_env *env,
|
||||||
struct bpf_verifier_state *cur)
|
struct bpf_verifier_state *cur)
|
||||||
@@ -2530,9 +2520,6 @@ static int push_jmp_history(struct bpf_verifier_env *env,
|
|||||||
struct bpf_idx_pair *p;
|
struct bpf_idx_pair *p;
|
||||||
size_t alloc_size;
|
size_t alloc_size;
|
||||||
|
|
||||||
if (!is_jmp_point(env, env->insn_idx))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cnt++;
|
cnt++;
|
||||||
alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p)));
|
alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p)));
|
||||||
p = krealloc(cur->jmp_history, alloc_size, GFP_USER);
|
p = krealloc(cur->jmp_history, alloc_size, GFP_USER);
|
||||||
@@ -11030,16 +11017,11 @@ static struct bpf_verifier_state_list **explored_state(
|
|||||||
return &env->explored_states[(idx ^ state->callsite) % state_htab_size(env)];
|
return &env->explored_states[(idx ^ state->callsite) % state_htab_size(env)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_prune_point(struct bpf_verifier_env *env, int idx)
|
static void init_explored_state(struct bpf_verifier_env *env, int idx)
|
||||||
{
|
{
|
||||||
env->insn_aux_data[idx].prune_point = true;
|
env->insn_aux_data[idx].prune_point = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_prune_point(struct bpf_verifier_env *env, int insn_idx)
|
|
||||||
{
|
|
||||||
return env->insn_aux_data[insn_idx].prune_point;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DONE_EXPLORING = 0,
|
DONE_EXPLORING = 0,
|
||||||
KEEP_EXPLORING = 1,
|
KEEP_EXPLORING = 1,
|
||||||
@@ -11068,11 +11050,9 @@ static int push_insn(int t, int w, int e, struct bpf_verifier_env *env,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e == BRANCH) {
|
if (e == BRANCH)
|
||||||
/* mark branch target for state pruning */
|
/* mark branch target for state pruning */
|
||||||
mark_prune_point(env, w);
|
init_explored_state(env, w);
|
||||||
mark_jmp_point(env, w);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (insn_state[w] == 0) {
|
if (insn_state[w] == 0) {
|
||||||
/* tree-edge */
|
/* tree-edge */
|
||||||
@@ -11110,13 +11090,10 @@ static int visit_func_call_insn(int t, int insn_cnt,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (t + 1 < insn_cnt) {
|
if (t + 1 < insn_cnt)
|
||||||
mark_prune_point(env, t + 1);
|
init_explored_state(env, t + 1);
|
||||||
mark_jmp_point(env, t + 1);
|
|
||||||
}
|
|
||||||
if (visit_callee) {
|
if (visit_callee) {
|
||||||
mark_prune_point(env, t);
|
init_explored_state(env, t);
|
||||||
mark_jmp_point(env, t);
|
|
||||||
ret = push_insn(t, t + insns[t].imm + 1, BRANCH, env,
|
ret = push_insn(t, t + insns[t].imm + 1, BRANCH, env,
|
||||||
/* It's ok to allow recursion from CFG point of
|
/* It's ok to allow recursion from CFG point of
|
||||||
* view. __check_func_call() will do the actual
|
* view. __check_func_call() will do the actual
|
||||||
@@ -11150,15 +11127,13 @@ static int visit_insn(int t, int insn_cnt, struct bpf_verifier_env *env)
|
|||||||
return DONE_EXPLORING;
|
return DONE_EXPLORING;
|
||||||
|
|
||||||
case BPF_CALL:
|
case BPF_CALL:
|
||||||
if (insns[t].imm == BPF_FUNC_timer_set_callback) {
|
if (insns[t].imm == BPF_FUNC_timer_set_callback)
|
||||||
/* Mark this call insn to trigger is_state_visited() check
|
/* Mark this call insn to trigger is_state_visited() check
|
||||||
* before call itself is processed by __check_func_call().
|
* before call itself is processed by __check_func_call().
|
||||||
* Otherwise new async state will be pushed for further
|
* Otherwise new async state will be pushed for further
|
||||||
* exploration.
|
* exploration.
|
||||||
*/
|
*/
|
||||||
mark_prune_point(env, t);
|
init_explored_state(env, t);
|
||||||
mark_jmp_point(env, t);
|
|
||||||
}
|
|
||||||
return visit_func_call_insn(t, insn_cnt, insns, env,
|
return visit_func_call_insn(t, insn_cnt, insns, env,
|
||||||
insns[t].src_reg == BPF_PSEUDO_CALL);
|
insns[t].src_reg == BPF_PSEUDO_CALL);
|
||||||
|
|
||||||
@@ -11176,22 +11151,18 @@ static int visit_insn(int t, int insn_cnt, struct bpf_verifier_env *env)
|
|||||||
* but it's marked, since backtracking needs
|
* but it's marked, since backtracking needs
|
||||||
* to record jmp history in is_state_visited().
|
* to record jmp history in is_state_visited().
|
||||||
*/
|
*/
|
||||||
mark_prune_point(env, t + insns[t].off + 1);
|
init_explored_state(env, t + insns[t].off + 1);
|
||||||
mark_jmp_point(env, t + insns[t].off + 1);
|
|
||||||
/* tell verifier to check for equivalent states
|
/* tell verifier to check for equivalent states
|
||||||
* after every call and jump
|
* after every call and jump
|
||||||
*/
|
*/
|
||||||
if (t + 1 < insn_cnt) {
|
if (t + 1 < insn_cnt)
|
||||||
mark_prune_point(env, t + 1);
|
init_explored_state(env, t + 1);
|
||||||
mark_jmp_point(env, t + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* conditional jump with two edges */
|
/* conditional jump with two edges */
|
||||||
mark_prune_point(env, t);
|
init_explored_state(env, t);
|
||||||
mark_jmp_point(env, t);
|
|
||||||
ret = push_insn(t, t + 1, FALLTHROUGH, env, true);
|
ret = push_insn(t, t + 1, FALLTHROUGH, env, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -12224,11 +12195,11 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
|
|||||||
bool add_new_state = env->test_state_freq ? true : false;
|
bool add_new_state = env->test_state_freq ? true : false;
|
||||||
|
|
||||||
cur->last_insn_idx = env->prev_insn_idx;
|
cur->last_insn_idx = env->prev_insn_idx;
|
||||||
if (!is_prune_point(env, insn_idx))
|
if (!env->insn_aux_data[insn_idx].prune_point)
|
||||||
/* this 'insn_idx' instruction wasn't marked, so we will not
|
/* this 'insn_idx' instruction wasn't marked, so we will not
|
||||||
* be doing state search here
|
* be doing state search here
|
||||||
*/
|
*/
|
||||||
return push_jmp_history(env, cur);
|
return 0;
|
||||||
|
|
||||||
/* bpf progs typically have pruning point every 4 instructions
|
/* bpf progs typically have pruning point every 4 instructions
|
||||||
* http://vger.kernel.org/bpfconf2019.html#session-1
|
* http://vger.kernel.org/bpfconf2019.html#session-1
|
||||||
|
|||||||
Reference in New Issue
Block a user