Revert "bpf: Fix reference state management for synchronous callbacks"
This reverts commit 4ed5155043 which is
commit 9d9d00ac29d0ef7ce426964de46fa6b380357d0a upstream.
It breaks the Android kernel ABI and is not needed for normal Android
systems so it is safe to remove. If it is needed in the future, it can
be brought back in an abi-safe way.
Bug: 161946584
Change-Id: Idc9e43f0bc47de086cefd5cd572ce8295bbb7b08
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -193,17 +193,6 @@ struct bpf_reference_state {
|
||||
* is used purely to inform the user of a reference leak.
|
||||
*/
|
||||
int insn_idx;
|
||||
/* There can be a case like:
|
||||
* main (frame 0)
|
||||
* cb (frame 1)
|
||||
* func (frame 3)
|
||||
* cb (frame 4)
|
||||
* Hence for frame 4, if callback_ref just stored boolean, it would be
|
||||
* impossible to distinguish nested callback refs. Hence store the
|
||||
* frameno and compare that to callback_ref in check_reference_leak when
|
||||
* exiting a callback function.
|
||||
*/
|
||||
int callback_ref;
|
||||
};
|
||||
|
||||
/* state of the program:
|
||||
|
||||
@@ -851,7 +851,6 @@ static int acquire_reference_state(struct bpf_verifier_env *env, int insn_idx)
|
||||
id = ++env->id_gen;
|
||||
state->refs[new_ofs].id = id;
|
||||
state->refs[new_ofs].insn_idx = insn_idx;
|
||||
state->refs[new_ofs].callback_ref = state->in_callback_fn ? state->frameno : 0;
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -864,9 +863,6 @@ static int release_reference_state(struct bpf_func_state *state, int ptr_id)
|
||||
last_idx = state->acquired_refs - 1;
|
||||
for (i = 0; i < state->acquired_refs; i++) {
|
||||
if (state->refs[i].id == ptr_id) {
|
||||
/* Cannot release caller references in callbacks */
|
||||
if (state->in_callback_fn && state->refs[i].callback_ref != state->frameno)
|
||||
return -EINVAL;
|
||||
if (last_idx && i != last_idx)
|
||||
memcpy(&state->refs[i], &state->refs[last_idx],
|
||||
sizeof(*state->refs));
|
||||
@@ -6009,17 +6005,10 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
|
||||
caller->regs[BPF_REG_0] = *r0;
|
||||
}
|
||||
|
||||
/* callback_fn frame should have released its own additions to parent's
|
||||
* reference state at this point, or check_reference_leak would
|
||||
* complain, hence it must be the same as the caller. There is no need
|
||||
* to copy it back.
|
||||
*/
|
||||
if (!callee->in_callback_fn) {
|
||||
/* Transfer references to the caller */
|
||||
err = copy_reference_state(caller, callee);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/* Transfer references to the caller */
|
||||
err = copy_reference_state(caller, callee);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*insn_idx = callee->callsite + 1;
|
||||
if (env->log.level & BPF_LOG_LEVEL) {
|
||||
@@ -6140,20 +6129,13 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
|
||||
static int check_reference_leak(struct bpf_verifier_env *env)
|
||||
{
|
||||
struct bpf_func_state *state = cur_func(env);
|
||||
bool refs_lingering = false;
|
||||
int i;
|
||||
|
||||
if (state->frameno && !state->in_callback_fn)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < state->acquired_refs; i++) {
|
||||
if (state->in_callback_fn && state->refs[i].callback_ref != state->frameno)
|
||||
continue;
|
||||
verbose(env, "Unreleased reference id=%d alloc_insn=%d\n",
|
||||
state->refs[i].id, state->refs[i].insn_idx);
|
||||
refs_lingering = true;
|
||||
}
|
||||
return refs_lingering ? -EINVAL : 0;
|
||||
return state->acquired_refs ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int check_bpf_snprintf_call(struct bpf_verifier_env *env,
|
||||
@@ -11168,16 +11150,6 @@ static int do_check(struct bpf_verifier_env *env)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We must do check_reference_leak here before
|
||||
* prepare_func_exit to handle the case when
|
||||
* state->curframe > 0, it may be a callback
|
||||
* function, for which reference_state must
|
||||
* match caller reference state when it exits.
|
||||
*/
|
||||
err = check_reference_leak(env);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (state->curframe) {
|
||||
/* exit from nested function */
|
||||
err = prepare_func_exit(env, &env->insn_idx);
|
||||
@@ -11187,6 +11159,10 @@ static int do_check(struct bpf_verifier_env *env)
|
||||
continue;
|
||||
}
|
||||
|
||||
err = check_reference_leak(env);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = check_return_code(env);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user