Skip to content

Commit f233d48

Browse files
kkdwvdAlexei Starovoitov
authored andcommitted
bpf: Refactor storage_get_func_atomic to generic non_sleepable flag
Rename the storage_get_func_atomic flag to a more generic non_sleepable flag that tracks whether a helper or kfunc may be called from a non-sleepable context. This makes the flag more broadly applicable beyond just storage_get helpers. See [0] for more context. The flag is now set unconditionally for all helpers and kfuncs when: - RCU critical section is active. - Preemption is disabled. - IRQs are disabled. - In a non-sleepable context within a sleepable program (e.g., timer callbacks), which is indicated by !in_sleepable(). Previously, the flag was only set for storage_get helpers in these contexts. With this change, it can be used by any code that needs to differentiate between sleepable and non-sleepable contexts at the per-instruction level. The existing usage in do_misc_fixups() for storage_get helpers is preserved by checking is_storage_get_function() before using the flag. [0]: https://lore.kernel.org/bpf/CAP01T76cbaNi4p-y8E0sjE2NXSra2S=Uja8G4hSQDu_SbXxREQ@mail.gmail.com Cc: Mykyta Yatsenko <[email protected]> Signed-off-by: Kumar Kartikeya Dwivedi <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Acked-by: Mykyta Yatsenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 469d638 commit f233d48

File tree

2 files changed

+18
-17
lines changed

2 files changed

+18
-17
lines changed

include/linux/bpf_verifier.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ struct bpf_insn_aux_data {
548548
bool nospec_result; /* result is unsafe under speculation, nospec must follow */
549549
bool zext_dst; /* this insn zero extends dst reg */
550550
bool needs_zext; /* alu op needs to clear upper bits */
551-
bool storage_get_func_atomic; /* bpf_*_storage_get() with atomic memory alloc */
551+
bool non_sleepable; /* helper/kfunc may be called from non-sleepable context */
552552
bool is_iter_next; /* bpf_iter_<type>_next() kfunc call */
553553
bool call_with_percpu_alloc_ptr; /* {this,per}_cpu_ptr() with prog percpu alloc */
554554
u8 alu_state; /* used in combination with alu_limit */

kernel/bpf/verifier.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11371,6 +11371,15 @@ static int get_helper_proto(struct bpf_verifier_env *env, int func_id,
1137111371
return *ptr && (*ptr)->func ? 0 : -EINVAL;
1137211372
}
1137311373

11374+
/* Check if we're in a sleepable context. */
11375+
static inline bool in_sleepable_context(struct bpf_verifier_env *env)
11376+
{
11377+
return !env->cur_state->active_rcu_lock &&
11378+
!env->cur_state->active_preempt_locks &&
11379+
!env->cur_state->active_irq_id &&
11380+
in_sleepable(env);
11381+
}
11382+
1137411383
static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1137511384
int *insn_idx_p)
1137611385
{
@@ -11437,9 +11446,6 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1143711446
func_id_name(func_id), func_id);
1143811447
return -EINVAL;
1143911448
}
11440-
11441-
if (is_storage_get_function(func_id))
11442-
env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
1144311449
}
1144411450

1144511451
if (env->cur_state->active_preempt_locks) {
@@ -11448,9 +11454,6 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1144811454
func_id_name(func_id), func_id);
1144911455
return -EINVAL;
1145011456
}
11451-
11452-
if (is_storage_get_function(func_id))
11453-
env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
1145411457
}
1145511458

1145611459
if (env->cur_state->active_irq_id) {
@@ -11459,17 +11462,11 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1145911462
func_id_name(func_id), func_id);
1146011463
return -EINVAL;
1146111464
}
11462-
11463-
if (is_storage_get_function(func_id))
11464-
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;
11467+
/* Track non-sleepable context for helpers. */
11468+
if (!in_sleepable_context(env))
11469+
env->insn_aux_data[insn_idx].non_sleepable = true;
1147311470

1147411471
meta.func_id = func_id;
1147511472
/* check args */
@@ -13880,6 +13877,10 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1388013877
return -EACCES;
1388113878
}
1388213879

13880+
/* Track non-sleepable context for kfuncs, same as for helpers. */
13881+
if (!in_sleepable_context(env))
13882+
insn_aux->non_sleepable = true;
13883+
1388313884
/* Check the arguments */
1388413885
err = check_kfunc_args(env, &meta, insn_idx);
1388513886
if (err < 0)
@@ -22502,7 +22503,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
2250222503
}
2250322504

2250422505
if (is_storage_get_function(insn->imm)) {
22505-
if (env->insn_aux_data[i + delta].storage_get_func_atomic)
22506+
if (env->insn_aux_data[i + delta].non_sleepable)
2250622507
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_ATOMIC);
2250722508
else
2250822509
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_KERNEL);

0 commit comments

Comments
 (0)