@@ -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;
@@ -5880,7 +5880,7 @@ static bool in_sleepable(struct bpf_verifier_env *env)
58805880 */
58815881static bool in_rcu_cs(struct bpf_verifier_env *env)
58825882{
5883- return env->cur_state->active_rcu_lock ||
5883+ return env->cur_state->active_rcu_locks ||
58845884 env->cur_state->active_locks ||
58855885 !in_sleepable(env);
58865886}
@@ -10735,7 +10735,7 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1073510735 }
1073610736
1073710737 if (env->subprog_info[subprog].might_sleep &&
10738- (env->cur_state->active_rcu_lock || env->cur_state->active_preempt_locks ||
10738+ (env->cur_state->active_rcu_locks || env->cur_state->active_preempt_locks ||
1073910739 env->cur_state->active_irq_id || !in_sleepable(env))) {
1074010740 verbose(env, "global functions that may sleep are not allowed in non-sleepable context,\n"
1074110741 "i.e., in a RCU/IRQ/preempt-disabled section, or in\n"
@@ -11314,7 +11314,7 @@ static int check_resource_leak(struct bpf_verifier_env *env, bool exception_exit
1131411314 return -EINVAL;
1131511315 }
1131611316
11317- if (check_lock && env->cur_state->active_rcu_lock ) {
11317+ if (check_lock && env->cur_state->active_rcu_locks ) {
1131811318 verbose(env, "%s cannot be used inside bpf_rcu_read_lock-ed region\n", prefix);
1131911319 return -EINVAL;
1132011320 }
@@ -11452,7 +11452,7 @@ static int get_helper_proto(struct bpf_verifier_env *env, int func_id,
1145211452/* Check if we're in a sleepable context. */
1145311453static inline bool in_sleepable_context(struct bpf_verifier_env *env)
1145411454{
11455- return !env->cur_state->active_rcu_lock &&
11455+ return !env->cur_state->active_rcu_locks &&
1145611456 !env->cur_state->active_preempt_locks &&
1145711457 !env->cur_state->active_irq_id &&
1145811458 in_sleepable(env);
@@ -11518,7 +11518,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1151811518 return err;
1151911519 }
1152011520
11521- if (env->cur_state->active_rcu_lock ) {
11521+ if (env->cur_state->active_rcu_locks ) {
1152211522 if (fn->might_sleep) {
1152311523 verbose(env, "sleepable helper %s#%d in rcu_read_lock region\n",
1152411524 func_id_name(func_id), func_id);
@@ -14006,36 +14006,33 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1400614006 preempt_disable = is_kfunc_bpf_preempt_disable(&meta);
1400714007 preempt_enable = is_kfunc_bpf_preempt_enable(&meta);
1400814008
14009- if (env->cur_state->active_rcu_lock) {
14009+ if (rcu_lock) {
14010+ env->cur_state->active_rcu_locks++;
14011+ } else if (rcu_unlock) {
1401014012 struct bpf_func_state *state;
1401114013 struct bpf_reg_state *reg;
1401214014 u32 clear_mask = (1 << STACK_SPILL) | (1 << STACK_ITER);
1401314015
14014- if (in_rbtree_lock_required_cb(env) && (rcu_lock || rcu_unlock)) {
14015- verbose(env, "Calling bpf_rcu_read_{lock,unlock} in unnecessary rbtree callback\n");
14016- return -EACCES;
14017- }
14018-
14019- if (rcu_lock) {
14020- verbose(env, "nested rcu read lock (kernel function %s)\n", func_name);
14016+ if (env->cur_state->active_rcu_locks == 0) {
14017+ verbose(env, "unmatched rcu read unlock (kernel function %s)\n", func_name);
1402114018 return -EINVAL;
14022- } else if (rcu_unlock) {
14019+ }
14020+ if (--env->cur_state->active_rcu_locks == 0) {
1402314021 bpf_for_each_reg_in_vstate_mask(env->cur_state, state, reg, clear_mask, ({
1402414022 if (reg->type & MEM_RCU) {
1402514023 reg->type &= ~(MEM_RCU | PTR_MAYBE_NULL);
1402614024 reg->type |= PTR_UNTRUSTED;
1402714025 }
1402814026 }));
14029- env->cur_state->active_rcu_lock = false;
14030- } else if (sleepable) {
14031- verbose(env, "kernel func %s is sleepable within rcu_read_lock region\n", func_name);
14032- return -EACCES;
1403314027 }
14034- } else if (rcu_lock) {
14035- env->cur_state->active_rcu_lock = true;
14036- } else if (rcu_unlock) {
14037- verbose(env, "unmatched rcu read unlock (kernel function %s)\n", func_name);
14038- return -EINVAL;
14028+ } else if (sleepable && env->cur_state->active_rcu_locks) {
14029+ verbose(env, "kernel func %s is sleepable within rcu_read_lock region\n", func_name);
14030+ return -EACCES;
14031+ }
14032+
14033+ if (in_rbtree_lock_required_cb(env) && (rcu_lock || rcu_unlock)) {
14034+ verbose(env, "Calling bpf_rcu_read_{lock,unlock} in unnecessary rbtree callback\n");
14035+ return -EACCES;
1403914036 }
1404014037
1404114038 if (env->cur_state->active_preempt_locks) {
@@ -19328,7 +19325,7 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
1932819325 if (old->active_preempt_locks != cur->active_preempt_locks)
1932919326 return false;
1933019327
19331- if (old->active_rcu_lock != cur->active_rcu_lock )
19328+ if (old->active_rcu_locks != cur->active_rcu_locks )
1933219329 return false;
1933319330
1933419331 if (!check_ids(old->active_irq_id, cur->active_irq_id, idmap))
0 commit comments