From: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>
To: "Kumar Kartikeya Dwivedi" <memxor@gmail.com>, <bpf@vger.kernel.org>
Cc: "Alexei Starovoitov" <ast@kernel.org>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Daniel Borkmann" <daniel@iogearbox.net>,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Emil Tsalapatis" <emil@etsalapatis.com>, <kkd@meta.com>,
<kernel-team@meta.com>
Subject: Re: [PATCH bpf-next v2 10/17] bpf: Report Resource Lifetime reference leaks
Date: Fri, 19 Jun 2026 16:42:33 -0700 [thread overview]
Message-ID: <DJDFA66W97OU.2VSS5QIMHBXCJ@gmail.com> (raw)
In-Reply-To: <20260619205934.1312876-11-memxor@gmail.com>
On Fri Jun 19, 2026 at 1:59 PM PDT, Kumar Kartikeya Dwivedi wrote:
> + bpf_diag_report_irq_resource_state(env, env->insn_idx,
> + "IRQ flag restore mismatch",
> + bpf_diag_scratch_printf(env,
> + 0,
> + "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.",
> + flag_kfunc,
> + used_kfunc),
> + "Restore the flag with the matching IRQ restore kfunc for the save operation that created it.",
> + env->cur_state->active_irq_id ? 1 : 0);
same concern as in the previous patch.
> return -EINVAL;
> }
>
> @@ -1137,6 +1150,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_report_irq_resource_state(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.",
> + env->cur_state->active_irq_id ? 1 : 0);
> return err;
> }
>
> @@ -7258,11 +7276,19 @@ static int process_spin_lock(struct bpf_verifier_env *env, struct bpf_reg_state
> if (find_lock_state(env->cur_state, REF_TYPE_LOCK, 0, NULL)) {
> verbose(env,
> "Locking two bpf_spin_locks are not allowed\n");
> + bpf_diag_report_resource_state(env, env->insn_idx,
> + "nested spin lock",
> + "This path already holds a bpf_spin_lock. The verifier allows only one regular BPF spin lock at a time.",
> + "Unlock the current bpf_spin_lock before taking another one.");
> return -EINVAL;
> }
> } else if (is_res_lock && cur->active_locks) {
> if (find_lock_state(env->cur_state, REF_TYPE_RES_LOCK | REF_TYPE_RES_LOCK_IRQ, reg->id, ptr)) {
> verbose(env, "Acquiring the same lock again, AA deadlock detected\n");
> + bpf_diag_report_resource_state(env, env->insn_idx,
> + "recursive resource spin lock",
> + "This path already holds the same resource spin lock. Taking it again would deadlock.",
> + "Avoid reacquiring the same resource spin lock before it is unlocked.");
> return -EINVAL;
> }
> }
> @@ -7289,6 +7315,10 @@ static int process_spin_lock(struct bpf_verifier_env *env, struct bpf_reg_state
>
> if (!cur->active_locks) {
> verbose(env, "%s_unlock without taking a lock\n", lock_str);
> + bpf_diag_report_resource_state(env, env->insn_idx,
> + "unlock without lock",
> + "This unlock operation has no matching active lock on the current path.",
> + "Take the matching lock before this unlock, or remove the unmatched unlock path.");
> return -EINVAL;
> }
>
> @@ -7300,14 +7330,26 @@ static int process_spin_lock(struct bpf_verifier_env *env, struct bpf_reg_state
> type = REF_TYPE_LOCK;
> if (!find_lock_state(cur, type, reg->id, ptr)) {
> verbose(env, "%s_unlock of different lock\n", lock_str);
> + bpf_diag_report_resource_state(env, env->insn_idx,
> + "unlock of different lock",
> + "This unlock does not match any active lock with the same tracked identity on the current path.",
> + "Unlock the same lock object that was most recently acquired.");
> return -EINVAL;
> }
> if (reg->id != cur->active_lock_id || ptr != cur->active_lock_ptr) {
> verbose(env, "%s_unlock cannot be out of order\n", lock_str);
> + bpf_diag_report_resource_state(env, env->insn_idx,
> + "unlock out of order",
> + "Locks must be released in last-in, first-out order, but this unlock does not match the currently active lock.",
> + "Release nested locks in the reverse order they were acquired.");
> return -EINVAL;
> }
> if (release_lock_state(env, type, reg->id, ptr)) {
> verbose(env, "%s_unlock of different lock\n", lock_str);
> + bpf_diag_report_resource_state(env, env->insn_idx,
> + "unlock of different lock",
> + "The verifier could not release a lock state matching this unlock operation.",
> + "Pass the same lock object and lock kind that were used for the matching lock operation.");
> return -EINVAL;
> }
>
> @@ -7473,6 +7515,10 @@ static int process_dynptr_func(struct bpf_verifier_env *env, struct bpf_reg_stat
> verbose(env,
> "%s expected pointer to stack or const struct bpf_dynptr\n",
> reg_arg_name(env, argno));
> + bpf_diag_report_resource_state(env, insn_idx,
> + "invalid dynptr argument",
> + "A dynptr argument must be a pointer to a dynptr stack slot or a verifier-provided const struct bpf_dynptr.",
> + "Pass the address of a stack dynptr object, or use a const dynptr pointer returned by the verifier-supported path.");
> return -EINVAL;
> }
>
> @@ -7495,6 +7541,10 @@ static int process_dynptr_func(struct bpf_verifier_env *env, struct bpf_reg_stat
>
> if (!is_dynptr_reg_valid_uninit(env, reg)) {
> verbose(env, "Dynptr has to be an uninitialized dynptr\n");
> + bpf_diag_report_resource_state(env, insn_idx,
> + "dynptr is already initialized",
> + "This kfunc constructs a dynptr and requires an uninitialized dynptr stack slot, but the selected slot already holds dynptr state.",
> + "Use a fresh stack dynptr slot, or release/destroy the existing dynptr before reusing the slot.");
> return -EINVAL;
> }
>
> @@ -7511,12 +7561,20 @@ static int process_dynptr_func(struct bpf_verifier_env *env, struct bpf_reg_stat
> /* For the reg->type == PTR_TO_STACK case, bpf_dynptr is never const */
> if (reg->type == CONST_PTR_TO_DYNPTR && (arg_type & OBJ_RELEASE)) {
> verbose(env, "CONST_PTR_TO_DYNPTR cannot be released\n");
> + bpf_diag_report_resource_state(env, insn_idx,
> + "const dynptr release",
> + "This release operation was given a const dynptr. Const dynptr values are verifier-provided views and cannot be released by the program.",
> + "Release only mutable dynptrs that the program initialized or reserved.");
> return -EINVAL;
> }
>
> if (!is_dynptr_reg_valid_init(env, reg)) {
> verbose(env, "Expected an initialized dynptr as %s\n",
> reg_arg_name(env, argno));
> + bpf_diag_report_resource_state(env, insn_idx,
> + "uninitialized dynptr use",
> + "This operation requires an initialized dynptr, but the stack slot does not currently hold a valid dynptr on this path.",
> + "Initialize the dynptr on every path before this call, and avoid overwriting or releasing it before this use.");
> return -EINVAL;
> }
>
> @@ -7526,6 +7584,10 @@ static int process_dynptr_func(struct bpf_verifier_env *env, struct bpf_reg_stat
> "Expected a dynptr of type %s as %s\n",
> dynptr_type_str(arg_to_dynptr_type(arg_type)),
> reg_arg_name(env, argno));
> + bpf_diag_report_resource_state(env, insn_idx,
> + "wrong dynptr type",
> + "The dynptr is initialized, but it was created for a different backing object type than this operation accepts.",
> + "Use a dynptr constructor that matches this operation, or call an operation that accepts the dynptr's current type.");
> return -EINVAL;
> }
>
> @@ -7594,6 +7656,10 @@ static int process_iter_arg(struct bpf_verifier_env *env, struct bpf_reg_state *
> if (reg->type != PTR_TO_STACK) {
> verbose(env, "%s expected pointer to an iterator on stack\n",
> reg_arg_name(env, argno));
> + bpf_diag_report_resource_state(env, insn_idx,
> + "invalid iterator argument",
> + "Iterator state must live in verifier-tracked stack memory, but this argument is not a stack pointer.",
> + "Pass the address of a stack iterator object for iterator new, next, and destroy calls.");
> return -EINVAL;
> }
>
> @@ -7607,6 +7673,10 @@ static int process_iter_arg(struct bpf_verifier_env *env, struct bpf_reg_state *
> if (btf_id < 0) {
> verbose(env, "expected valid iter pointer as %s\n",
> reg_arg_name(env, argno));
> + bpf_diag_report_resource_state(env, insn_idx,
> + "invalid iterator type",
> + "The kfunc expects a recognized iterator state pointer, but this argument does not match a valid iterator type.",
> + "Pass the exact iterator state type expected by this kfunc.");
> return -EINVAL;
> }
> t = btf_type_by_id(meta->btf, btf_id);
> @@ -7617,6 +7687,10 @@ static int process_iter_arg(struct bpf_verifier_env *env, struct bpf_reg_state *
> if (!is_iter_reg_valid_uninit(env, reg, nr_slots)) {
> verbose(env, "expected uninitialized iter_%s as %s\n",
> iter_type_str(meta->btf, btf_id), reg_arg_name(env, argno));
> + bpf_diag_report_resource_state(env, insn_idx,
> + "iterator is already initialized",
> + "Iterator creation requires an uninitialized iterator stack object, but this stack range already contains iterator state.",
> + "Use a fresh iterator stack slot, or destroy the existing iterator before reusing the slot.");
Maybe shorten bpf_diag_report_resource_state() name to bpf_diag() ?
next prev parent reply other threads:[~2026-06-19 23:42 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-19 20:59 [PATCH bpf-next v2 00/17] Redesign Verification Errors Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 01/17] bpf: Add verifier diagnostics report helpers Kumar Kartikeya Dwivedi
2026-06-19 21:09 ` sashiko-bot
2026-06-19 20:59 ` [PATCH bpf-next v2 02/17] bpf: Add source and instruction diagnostic context Kumar Kartikeya Dwivedi
2026-06-19 21:46 ` bot+bpf-ci
2026-06-19 20:59 ` [PATCH bpf-next v2 03/17] bpf: Add verifier diagnostic event log Kumar Kartikeya Dwivedi
2026-06-19 21:46 ` bot+bpf-ci
2026-06-19 20:59 ` [PATCH bpf-next v2 04/17] bpf: Prune verifier diagnostics on backtracking Kumar Kartikeya Dwivedi
2026-06-19 21:46 ` bot+bpf-ci
2026-06-19 20:59 ` [PATCH bpf-next v2 05/17] bpf: Track verifier register diagnostic events Kumar Kartikeya Dwivedi
2026-06-19 21:18 ` sashiko-bot
2026-06-19 23:35 ` Alexei Starovoitov
2026-06-19 20:59 ` [PATCH bpf-next v2 06/17] bpf: Track verifier reference " Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 07/17] bpf: Track verifier context " Kumar Kartikeya Dwivedi
2026-06-19 21:13 ` sashiko-bot
2026-06-19 21:19 ` Kumar Kartikeya Dwivedi
2026-06-19 21:46 ` bot+bpf-ci
2026-06-19 20:59 ` [PATCH bpf-next v2 08/17] bpf: Report Register Type Safety errors Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 09/17] bpf: Report Memory Safety bounds errors Kumar Kartikeya Dwivedi
2026-06-19 21:46 ` bot+bpf-ci
2026-06-19 23:40 ` Alexei Starovoitov
2026-06-19 20:59 ` [PATCH bpf-next v2 10/17] bpf: Report Resource Lifetime reference leaks Kumar Kartikeya Dwivedi
2026-06-19 21:12 ` sashiko-bot
2026-06-19 23:42 ` Alexei Starovoitov [this message]
2026-06-19 20:59 ` [PATCH bpf-next v2 11/17] bpf: Report Call Type Safety argument errors Kumar Kartikeya Dwivedi
2026-06-19 21:47 ` bot+bpf-ci
2026-06-19 20:59 ` [PATCH bpf-next v2 12/17] bpf: Report Execution Context Safety errors Kumar Kartikeya Dwivedi
2026-06-19 21:19 ` sashiko-bot
2026-06-19 23:44 ` Alexei Starovoitov
2026-06-19 20:59 ` [PATCH bpf-next v2 13/17] bpf: Report Program Structure CFG errors Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 14/17] bpf: Report Policy helper and kfunc errors Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 15/17] bpf: Report Verifier Limit errors Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 16/17] bpf: Report Verifier Internal errors Kumar Kartikeya Dwivedi
2026-06-19 20:59 ` [PATCH bpf-next v2 17/17] bpf: Gate verifier diagnostics on log level Kumar Kartikeya Dwivedi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DJDFA66W97OU.2VSS5QIMHBXCJ@gmail.com \
--to=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=kernel-team@meta.com \
--cc=kkd@meta.com \
--cc=memxor@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.