Skip to content

Commit 1cbc34a

Browse files
kkdwvdKernel Patches Daemon
authored andcommitted
bpf: Fix GFP flags for non-sleepable async callbacks
Fix storage_get helpers to use GFP_ATOMIC when called from non-sleepable contexts within sleepable programs, such as bpf_timer callbacks. Currently, the check in do_misc_fixups assumes that env->prog->sleepable, previously in_sleepable(env) which only resolved to this check before last commit, holds across the program's execution, but that is not true. Instead, the func_atomic bit must be set whenever we see the function being called in an atomic context. Previously, this is being done when the helper is invoked in atomic contexts in sleepable programs, we can simply just set the value to true without doing an in_sleepable() check. We must also do a standalone in_sleepable() check to handle cases where the async callback itself is armed from a sleepable program, but is itself non-sleepable (e.g., timer callback) and invokes such a helper, thus needing the func_atomic bit to be true for the said call. Adjust do_misc_fixups() to drop any checks regarding sleepable nature of the program, and just depend on the func_atomic bit to decide which GFP flag to pass. Fixes: b00fa38 ("bpf: Enable non-atomic allocations in local storage") Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]>
1 parent bf17063 commit 1cbc34a

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

kernel/bpf/verifier.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11438,7 +11438,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1143811438
return -EINVAL;
1143911439
}
1144011440

11441-
if (in_sleepable(env) && is_storage_get_function(func_id))
11441+
if (is_storage_get_function(func_id))
1144211442
env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
1144311443
}
1144411444

@@ -11449,7 +11449,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1144911449
return -EINVAL;
1145011450
}
1145111451

11452-
if (in_sleepable(env) && is_storage_get_function(func_id))
11452+
if (is_storage_get_function(func_id))
1145311453
env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
1145411454
}
1145511455

@@ -11460,10 +11460,17 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1146011460
return -EINVAL;
1146111461
}
1146211462

11463-
if (in_sleepable(env) && is_storage_get_function(func_id))
11463+
if (is_storage_get_function(func_id))
1146411464
env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
1146511465
}
1146611466

11467+
/*
11468+
* Non-sleepable contexts in sleepable programs (e.g., timer callbacks)
11469+
* are atomic and must use GFP_ATOMIC for storage_get helpers.
11470+
*/
11471+
if (!in_sleepable(env) && is_storage_get_function(func_id))
11472+
env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
11473+
1146711474
meta.func_id = func_id;
1146811475
/* check args */
1146911476
for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
@@ -22495,8 +22502,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
2249522502
}
2249622503

2249722504
if (is_storage_get_function(insn->imm)) {
22498-
if (!env->prog->sleepable ||
22499-
env->insn_aux_data[i + delta].storage_get_func_atomic)
22505+
if (env->insn_aux_data[i + delta].storage_get_func_atomic)
2250022506
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_ATOMIC);
2250122507
else
2250222508
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_KERNEL);

0 commit comments

Comments
 (0)