@@ -1437,7 +1437,7 @@ static int copy_reference_state(struct bpf_verifier_state *dst, const struct bpf
14371437 dst->acquired_refs = src->acquired_refs;
14381438 dst->active_locks = src->active_locks;
14391439 dst->active_preempt_locks = src->active_preempt_locks;
1440- dst->active_rcu_lock = src->active_rcu_lock ;
1440+ dst->active_rcu_locks = src->active_rcu_locks ;
14411441 dst->active_irq_id = src->active_irq_id;
14421442 dst->active_lock_id = src->active_lock_id;
14431443 dst->active_lock_ptr = src->active_lock_ptr;
@@ -5889,7 +5889,7 @@ static bool in_sleepable(struct bpf_verifier_env *env)
58895889 */
58905890static bool in_rcu_cs(struct bpf_verifier_env *env)
58915891{
5892- return env->cur_state->active_rcu_lock ||
5892+ return env->cur_state->active_rcu_locks ||
58935893 env->cur_state->active_locks ||
58945894 !in_sleepable(env);
58955895}
@@ -10744,7 +10744,7 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1074410744 }
1074510745
1074610746 if (env->subprog_info[subprog].might_sleep &&
10747- (env->cur_state->active_rcu_lock || env->cur_state->active_preempt_locks ||
10747+ (env->cur_state->active_rcu_locks || env->cur_state->active_preempt_locks ||
1074810748 env->cur_state->active_irq_id || !in_sleepable(env))) {
1074910749 verbose(env, "global functions that may sleep are not allowed in non-sleepable context,\n"
1075010750 "i.e., in a RCU/IRQ/preempt-disabled section, or in\n"
@@ -11327,7 +11327,7 @@ static int check_resource_leak(struct bpf_verifier_env *env, bool exception_exit
1132711327 return -EINVAL;
1132811328 }
1132911329
11330- if (check_lock && env->cur_state->active_rcu_lock ) {
11330+ if (check_lock && env->cur_state->active_rcu_locks ) {
1133111331 verbose(env, "%s cannot be used inside bpf_rcu_read_lock-ed region\n", prefix);
1133211332 return -EINVAL;
1133311333 }
@@ -11465,7 +11465,7 @@ static int get_helper_proto(struct bpf_verifier_env *env, int func_id,
1146511465/* Check if we're in a sleepable context. */
1146611466static inline bool in_sleepable_context(struct bpf_verifier_env *env)
1146711467{
11468- return !env->cur_state->active_rcu_lock &&
11468+ return !env->cur_state->active_rcu_locks &&
1146911469 !env->cur_state->active_preempt_locks &&
1147011470 !env->cur_state->active_irq_id &&
1147111471 in_sleepable(env);
@@ -11531,7 +11531,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1153111531 return err;
1153211532 }
1153311533
11534- if (env->cur_state->active_rcu_lock ) {
11534+ if (env->cur_state->active_rcu_locks ) {
1153511535 if (fn->might_sleep) {
1153611536 verbose(env, "sleepable helper %s#%d in rcu_read_lock region\n",
1153711537 func_id_name(func_id), func_id);
@@ -14038,36 +14038,33 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1403814038 preempt_disable = is_kfunc_bpf_preempt_disable(&meta);
1403914039 preempt_enable = is_kfunc_bpf_preempt_enable(&meta);
1404014040
14041- if (env->cur_state->active_rcu_lock) {
14041+ if (rcu_lock) {
14042+ env->cur_state->active_rcu_locks++;
14043+ } else if (rcu_unlock) {
1404214044 struct bpf_func_state *state;
1404314045 struct bpf_reg_state *reg;
1404414046 u32 clear_mask = (1 << STACK_SPILL) | (1 << STACK_ITER);
1404514047
14046- if (in_rbtree_lock_required_cb(env) && (rcu_lock || rcu_unlock)) {
14047- verbose(env, "Calling bpf_rcu_read_{lock,unlock} in unnecessary rbtree callback\n");
14048- return -EACCES;
14049- }
14050-
14051- if (rcu_lock) {
14052- verbose(env, "nested rcu read lock (kernel function %s)\n", func_name);
14048+ if (env->cur_state->active_rcu_locks == 0) {
14049+ verbose(env, "unmatched rcu read unlock (kernel function %s)\n", func_name);
1405314050 return -EINVAL;
14054- } else if (rcu_unlock) {
14051+ }
14052+ if (--env->cur_state->active_rcu_locks == 0) {
1405514053 bpf_for_each_reg_in_vstate_mask(env->cur_state, state, reg, clear_mask, ({
1405614054 if (reg->type & MEM_RCU) {
1405714055 reg->type &= ~(MEM_RCU | PTR_MAYBE_NULL);
1405814056 reg->type |= PTR_UNTRUSTED;
1405914057 }
1406014058 }));
14061- env->cur_state->active_rcu_lock = false;
14062- } else if (sleepable) {
14063- verbose(env, "kernel func %s is sleepable within rcu_read_lock region\n", func_name);
14064- return -EACCES;
1406514059 }
14066- } else if (rcu_lock) {
14067- env->cur_state->active_rcu_lock = true;
14068- } else if (rcu_unlock) {
14069- verbose(env, "unmatched rcu read unlock (kernel function %s)\n", func_name);
14070- return -EINVAL;
14060+ } else if (sleepable && env->cur_state->active_rcu_locks) {
14061+ verbose(env, "kernel func %s is sleepable within rcu_read_lock region\n", func_name);
14062+ return -EACCES;
14063+ }
14064+
14065+ if (in_rbtree_lock_required_cb(env) && (rcu_lock || rcu_unlock)) {
14066+ verbose(env, "Calling bpf_rcu_read_{lock,unlock} in unnecessary rbtree callback\n");
14067+ return -EACCES;
1407114068 }
1407214069
1407314070 if (env->cur_state->active_preempt_locks) {
@@ -19387,7 +19384,7 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
1938719384 if (old->active_preempt_locks != cur->active_preempt_locks)
1938819385 return false;
1938919386
19390- if (old->active_rcu_lock != cur->active_rcu_lock )
19387+ if (old->active_rcu_locks != cur->active_rcu_locks )
1939119388 return false;
1939219389
1939319390 if (!check_ids(old->active_irq_id, cur->active_irq_id, idmap))
0 commit comments