@@ -1434,6 +1434,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
14341434 }
14351435 dst_state->speculative = src->speculative;
14361436 dst_state->active_rcu_lock = src->active_rcu_lock;
1437+ dst_state->active_preempt_lock = src->active_preempt_lock;
14371438 dst_state->in_sleepable = src->in_sleepable;
14381439 dst_state->curframe = src->curframe;
14391440 dst_state->active_lock.ptr = src->active_lock.ptr;
@@ -9599,6 +9600,13 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
95999600 return -EINVAL;
96009601 }
96019602
9603+ /* Only global subprogs cannot be called with preemption disabled. */
9604+ if (env->cur_state->active_preempt_lock) {
9605+ verbose(env, "global function calls are not allowed with preemption disabled,\n"
9606+ "use static function instead\n");
9607+ return -EINVAL;
9608+ }
9609+
96029610 if (err) {
96039611 verbose(env, "Caller passes invalid args into func#%d ('%s')\n",
96049612 subprog, sub_name);
@@ -10285,6 +10293,17 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
1028510293 env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
1028610294 }
1028710295
10296+ if (env->cur_state->active_preempt_lock) {
10297+ if (fn->might_sleep) {
10298+ verbose(env, "sleepable helper %s#%d in non-preemptible region\n",
10299+ func_id_name(func_id), func_id);
10300+ return -EINVAL;
10301+ }
10302+
10303+ if (in_sleepable(env) && is_storage_get_function(func_id))
10304+ env->insn_aux_data[insn_idx].storage_get_func_atomic = true;
10305+ }
10306+
1028810307 meta.func_id = func_id;
1028910308 /* check args */
1029010309 for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
@@ -11027,6 +11046,8 @@ enum special_kfunc_type {
1102711046 KF_bpf_percpu_obj_drop_impl,
1102811047 KF_bpf_throw,
1102911048 KF_bpf_wq_set_callback_impl,
11049+ KF_bpf_preempt_disable,
11050+ KF_bpf_preempt_enable,
1103011051 KF_bpf_iter_css_task_new,
1103111052};
1103211053
@@ -11081,6 +11102,8 @@ BTF_ID(func, bpf_percpu_obj_new_impl)
1108111102BTF_ID(func, bpf_percpu_obj_drop_impl)
1108211103BTF_ID(func, bpf_throw)
1108311104BTF_ID(func, bpf_wq_set_callback_impl)
11105+ BTF_ID(func, bpf_preempt_disable)
11106+ BTF_ID(func, bpf_preempt_enable)
1108411107#ifdef CONFIG_CGROUPS
1108511108BTF_ID(func, bpf_iter_css_task_new)
1108611109#else
@@ -11107,6 +11130,16 @@ static bool is_kfunc_bpf_rcu_read_unlock(struct bpf_kfunc_call_arg_meta *meta)
1110711130 return meta->func_id == special_kfunc_list[KF_bpf_rcu_read_unlock];
1110811131}
1110911132
11133+ static bool is_kfunc_bpf_preempt_disable(struct bpf_kfunc_call_arg_meta *meta)
11134+ {
11135+ return meta->func_id == special_kfunc_list[KF_bpf_preempt_disable];
11136+ }
11137+
11138+ static bool is_kfunc_bpf_preempt_enable(struct bpf_kfunc_call_arg_meta *meta)
11139+ {
11140+ return meta->func_id == special_kfunc_list[KF_bpf_preempt_enable];
11141+ }
11142+
1111011143static enum kfunc_ptr_arg_type
1111111144get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
1111211145 struct bpf_kfunc_call_arg_meta *meta,
@@ -12195,11 +12228,11 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char
1219512228static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1219612229 int *insn_idx_p)
1219712230{
12198- const struct btf_type *t, *ptr_type ;
12231+ bool sleepable, rcu_lock, rcu_unlock, preempt_disable, preempt_enable ;
1219912232 u32 i, nargs, ptr_type_id, release_ref_obj_id;
1220012233 struct bpf_reg_state *regs = cur_regs(env);
1220112234 const char *func_name, *ptr_type_name;
12202- bool sleepable, rcu_lock, rcu_unlock ;
12235+ const struct btf_type *t, *ptr_type ;
1220312236 struct bpf_kfunc_call_arg_meta meta;
1220412237 struct bpf_insn_aux_data *insn_aux;
1220512238 int err, insn_idx = *insn_idx_p;
@@ -12260,6 +12293,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1226012293 rcu_lock = is_kfunc_bpf_rcu_read_lock(&meta);
1226112294 rcu_unlock = is_kfunc_bpf_rcu_read_unlock(&meta);
1226212295
12296+ preempt_disable = is_kfunc_bpf_preempt_disable(&meta);
12297+ preempt_enable = is_kfunc_bpf_preempt_enable(&meta);
12298+
1226312299 if (env->cur_state->active_rcu_lock) {
1226412300 struct bpf_func_state *state;
1226512301 struct bpf_reg_state *reg;
@@ -12292,6 +12328,22 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1229212328 return -EINVAL;
1229312329 }
1229412330
12331+ if (env->cur_state->active_preempt_lock) {
12332+ if (preempt_disable) {
12333+ env->cur_state->active_preempt_lock++;
12334+ } else if (preempt_enable) {
12335+ env->cur_state->active_preempt_lock--;
12336+ } else if (sleepable) {
12337+ verbose(env, "kernel func %s is sleepable within non-preemptible region\n", func_name);
12338+ return -EACCES;
12339+ }
12340+ } else if (preempt_disable) {
12341+ env->cur_state->active_preempt_lock++;
12342+ } else if (preempt_enable) {
12343+ verbose(env, "unmatched attempt to enable preemption (kernel function %s)\n", func_name);
12344+ return -EINVAL;
12345+ }
12346+
1229512347 /* In case of release function, we get register number of refcounted
1229612348 * PTR_TO_BTF_ID in bpf_kfunc_arg_meta, do the release now.
1229712349 */
@@ -15439,6 +15491,11 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
1543915491 return -EINVAL;
1544015492 }
1544115493
15494+ if (env->cur_state->active_preempt_lock) {
15495+ verbose(env, "BPF_LD_[ABS|IND] cannot be used inside bpf_preempt_disable-ed region\n");
15496+ return -EINVAL;
15497+ }
15498+
1544215499 if (regs[ctx_reg].type != PTR_TO_CTX) {
1544315500 verbose(env,
1544415501 "at the time of BPF_LD_ABS|IND R6 != pointer to skb\n");
@@ -17006,6 +17063,9 @@ static bool states_equal(struct bpf_verifier_env *env,
1700617063 if (old->active_rcu_lock != cur->active_rcu_lock)
1700717064 return false;
1700817065
17066+ if (old->active_preempt_lock != cur->active_preempt_lock)
17067+ return false;
17068+
1700917069 if (old->in_sleepable != cur->in_sleepable)
1701017070 return false;
1701117071
@@ -17957,6 +18017,13 @@ static int do_check(struct bpf_verifier_env *env)
1795718017 return -EINVAL;
1795818018 }
1795918019
18020+ if (env->cur_state->active_preempt_lock && !env->cur_state->curframe) {
18021+ verbose(env, "%d bpf_preempt_enable%s missing\n",
18022+ env->cur_state->active_preempt_lock,
18023+ env->cur_state->active_preempt_lock == 1 ? " is" : "(s) are");
18024+ return -EINVAL;
18025+ }
18026+
1796018027 /* We must do check_reference_leak here before
1796118028 * prepare_func_exit to handle the case when
1796218029 * state->curframe > 0, it may be a callback
0 commit comments