Re: [PATCH bpf-next v4 12/16] bpf: Report Execution Context Safety errors

Eduard Zingerman <[email protected]>
Newsgroups org.kernel.vger.bpf
Message-ID <[email protected]>
On Thu, 2026-08-13 at 01:33 +0200, Kumar Kartikeya Dwivedi wrote:

...

diff --git a/kernel/bpf/diagnostics.c b/kernel/bpf/diagnostics.c

...

+void bpf_diag_ctx(struct bpf_verifier_env *env, enum bpf_diag_ctx_report report, u32 insn_idx,
+		  const char *operation, enum bpf_diag_context_kind ctx_kind, const char *context,
+		  const char *suggestion)

Nit: expose diag_ctx_{forbidden,active,underflow} and drop this function and enum?

+{
+	switch (report) {
+	case BPF_DIAG_CTX_FORBIDDEN:
+		diag_ctx_forbidden(env, insn_idx, operation, ctx_kind, context,
+				   diag_context_constraint(ctx_kind), suggestion);
+		return;
+	case BPF_DIAG_CTX_ACTIVE:
+		diag_ctx_active(env, insn_idx, operation, ctx_kind, context, suggestion);
+		return;
+	case BPF_DIAG_CTX_UNDERFLOW:
+		diag_ctx_underflow(env, insn_idx, operation, ctx_kind, suggestion);
+		return;
+	}
+}

...

> @@ -2005,23 +2174,6 @@ static void diag_print_ref_event(struct bpf_verifier_env *env,
>  			       event->ref.ref_id);
>  }
>  
> -static const char *diag_context_name(enum bpf_diag_context_kind kind)
> -{
> -	switch (kind) {
> -	case BPF_DIAG_CONTEXT_RCU:
> -		return "RCU read lock region";
> -	case BPF_DIAG_CONTEXT_PREEMPT:
> -		return "non-preemptible region";
> -	case BPF_DIAG_CONTEXT_IRQ:
> -		return "IRQ-disabled region";
> -	case BPF_DIAG_CONTEXT_LOCK:
> -		return "lock region";
> -	case BPF_DIAG_CONTEXT_NONE:
> -	default:
> -		return "context";
> -	}
> -}

Nit: the move is churn.

...

> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 7e28f4d9f5c4..71893c36ecce 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c

...

> @@ -1104,9 +1106,7 @@ static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_r
>  	st = &slot->spilled_ptr;
>  
>  	if (st->irq.kfunc_class != kfunc_class) {
> -		const char *fmt = "This IRQ flag was saved by %s IRQ kfuncs, but the restore call "
> -				  "belongs to the %s IRQ kfunc family. Save and restore operations "
> -				  "must use the same family.";
> +		const char *fmt = "This IRQ flag was saved by %s IRQ kfuncs, but the restore call belongs to the %s IRQ kfunc family. Save and restore operations must use the same family.";

Churn.

>  		const char *flag_kfunc = st->irq.kfunc_class == IRQ_NATIVE_KFUNC ? "native" :
>  										   "lock";
>  		const char *used_kfunc = kfunc_class == IRQ_NATIVE_KFUNC ? "native" : "lock";
> @@ -1115,10 +1115,10 @@ static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_r
>  		verbose(env, "irq flag acquired by %s kfuncs cannot be restored with %s kfuncs\n",
>  			flag_kfunc, used_kfunc);
>  		reason = bpf_diag_fmt(env, fmt, flag_kfunc, used_kfunc);
> -		bpf_diag_irq(env, env->insn_idx, "IRQ flag restore mismatch", reason,
> -			     "Restore the flag with the matching IRQ restore kfunc for the save "
> -			     "operation that created it.",
> -			     bpf_diag_irq_depth(env->cur_state));
> +		bpf_diag_irq(
> +			env, env->insn_idx, "IRQ flag restore mismatch", reason,
> +			"Restore the flag with the matching IRQ restore kfunc for the save operation that created it.",
> +			bpf_diag_irq_depth(env->cur_state));

Churn.

>  		return -EINVAL;
>  	}
>  
> @@ -1136,11 +1136,11 @@ static int unmark_stack_slot_irq_flag(struct bpf_verifier_env *env, struct bpf_r
>  
>  		verbose(env, "cannot restore irq state out of order, expected id=%d acquired at insn_idx=%d\n",
>  			env->cur_state->active_irq_id, insn_idx);
> -		bpf_diag_irq(env, env->insn_idx, "IRQ flag restore out of order",
> -			     "IRQ-disabled regions must be restored in last-in, first-out order, "
> -			     "but this restore does not match the currently active IRQ flag.",
> -			     "Restore nested IRQ flags in the reverse order they were saved.",
> -			     bpf_diag_irq_depth(env->cur_state));
> +		bpf_diag_irq(
> +			env, env->insn_idx, "IRQ flag restore out of order",
> +			"IRQ-disabled regions must be restored in last-in, first-out order, but this restore does not match the currently active IRQ flag.",
> +			"Restore nested IRQ flags in the reverse order they were saved.",
> +			bpf_diag_irq_depth(env->cur_state));
>  		return err;

Churn.

>  	}
>  

...

> @@ -10551,6 +10578,36 @@ static const char *non_sleepable_context_description(struct bpf_verifier_env *en
>  	return "non-sleepable prog";
>  }
>  
> +static enum bpf_diag_context_kind non_sleepable_context_kind(struct bpf_verifier_env *env)
> +{
> +	if (env->cur_state->active_rcu_locks)
> +		return BPF_DIAG_CONTEXT_RCU;
> +	if (env->cur_state->active_preempt_locks)
> +		return BPF_DIAG_CONTEXT_PREEMPT;
> +	if (env->cur_state->active_irq_id)
> +		return BPF_DIAG_CONTEXT_IRQ;
> +	if (env->cur_state->active_locks)
> +		return BPF_DIAG_CONTEXT_LOCK;
> +	return BPF_DIAG_CONTEXT_NONE;
> +}
> +
> +static const char *non_sleepable_context_diag_description(struct bpf_verifier_env *env)

Drop the BPF_DIAG_CONTEXT_RCU & Co and use `const char *`?

> +{
> +	switch (non_sleepable_context_kind(env)) {
> +	case BPF_DIAG_CONTEXT_RCU:
> +		return "RCU read lock region";
> +	case BPF_DIAG_CONTEXT_PREEMPT:
> +		return "non-preemptible region";
> +	case BPF_DIAG_CONTEXT_IRQ:
> +		return "IRQ-disabled region";
> +	case BPF_DIAG_CONTEXT_LOCK:
> +		return "lock region";
> +	case BPF_DIAG_CONTEXT_NONE:
> +	default:
> +		return "non-sleepable program";
> +	}
> +}
> +
>  static int release_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
>  		       bool convert_rcu, bool release_dynptr)
>  {

...

> @@ -11919,12 +11983,10 @@ static int process_irq_flag(struct bpf_verifier_env *env, struct bpf_reg_state *
>  		if (!is_irq_flag_reg_valid_uninit(env, reg)) {
>  			verbose(env, "expected uninitialized irq flag as %s\n",
>  				reg_arg_name(env, argno));
> -			bpf_diag_res(env, env->insn_idx, "IRQ flag is already initialized",
> -				     "Saving IRQ state requires an uninitialized stack slot for "
> -				     "the IRQ flag, but this slot already contains tracked IRQ "
> -				     "flag state.",
> -				     "Use a fresh stack slot for this save operation, or restore "
> -				     "the existing IRQ flag before reusing the slot.");
> +			bpf_diag_res(
> +				env, env->insn_idx, "IRQ flag is already initialized",
> +				"Saving IRQ state requires an uninitialized stack slot for the IRQ flag, but this slot already contains tracked IRQ flag state.",
> +				"Use a fresh stack slot for this save operation, or restore the existing IRQ flag before reusing the slot.");

Churn.

>  			return -EINVAL;
>  		}
>  
> @@ -11941,11 +12003,10 @@ static int process_irq_flag(struct bpf_verifier_env *env, struct bpf_reg_state *
>  		if (err) {
>  			verbose(env, "expected an initialized irq flag as %s\n",
>  				reg_arg_name(env, argno));
> -			bpf_diag_res(env, env->insn_idx, "uninitialized IRQ flag restore",
> -				     "Restoring IRQ state requires a stack slot that was "
> -				     "initialized by a matching IRQ save operation on this path.",
> -				     "Pass the same stack slot that was previously initialized by "
> -				     "the matching IRQ save kfunc.");
> +			bpf_diag_res(
> +				env, env->insn_idx, "uninitialized IRQ flag restore",
> +				"Restoring IRQ state requires a stack slot that was initialized by a matching IRQ save operation on this path.",
> +				"Pass the same stack slot that was previously initialized by the matching IRQ save kfunc.");
>  			return err;

Churn.

...
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.