All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: bpf@vger.kernel.org
Cc: Nicholas Carlini <npc@anthropic.com>,
	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: [PATCH bpf-next v1 2/3] bpf: Bound local kptr ownership depth
Date: Sat,  5 Sep 2026 11:07:47 +0200	[thread overview]
Message-ID: <20260905090750.4064411-3-memxor@gmail.com> (raw)
In-Reply-To: <20260905090750.4064411-1-memxor@gmail.com>

Program BTF records can own other program-allocated objects through local
referenced kptrs. Releasing such an object follows the kptr through
bpf_obj_free_fields() and __bpf_obj_drop_impl().

The ownership graph walk only follows list and rbtree roots because
referenced kptrs originally supported kernel types with registered
destructors. Support for exchanging program-allocated objects into local
kptrs invalidated that assumption. A self-referential local kptr lets a
CAP_BPF user build an arbitrarily deep object chain, and dropping its head
can exhaust the kernel stack and panic the kernel. A sufficiently long
acyclic chain has the same problem.

Extend the bounded ownership walk to program-local referenced kptrs. A
pointee without special fields is absent from the struct metadata table and
adds only a final non-recursing drop.

Also include local percpu kptrs even though bpf_percpu_obj_new() currently
rejects types with special-field metadata. Rejecting unsafe ownership graphs
now keeps the depth invariant intact if that restriction is relaxed later.
Kernel-BTF kptrs remain outside the walk because they do not recurse through
program BTF records.

Fixes: b0966c724584 ("bpf: Support bpf_kptr_xchg into local kptr")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 kernel/bpf/btf.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 2a458499a236..3c508ebb2438 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -4313,20 +4313,28 @@ static int btf_owned_type_idx(const struct btf *btf, struct btf_struct_metas *ta
 	struct btf_struct_meta *meta;
 	u32 btf_id;
 
-	if (!(field->type & BPF_GRAPH_ROOT))
+	if (field->type & BPF_GRAPH_ROOT) {
+		btf_id = field->graph_root.value_btf_id;
+	} else if (field->type == BPF_KPTR_REF || field->type == BPF_KPTR_PERCPU) {
+		if (btf_is_kernel(field->kptr.btf))
+			return -ENOENT;
+		btf_id = field->kptr.btf_id;
+	} else {
 		return -ENOENT;
-	btf_id = field->graph_root.value_btf_id;
+	}
+
 	meta = btf_find_struct_meta(btf, btf_id);
 	if (!meta)
-		return -EFAULT;
+		return field->type & BPF_GRAPH_ROOT ? -EFAULT : -ENOENT;
 	return meta - tab->types;
 }
 
 /*
- * Each graph ownership edge adds kernel frames through
- * bpf_obj_free_fields() and __bpf_obj_drop_impl(). Keep the bound
- * deliberately small because object destruction can itself run below a BPF
- * call chain.
+ * Each ownership edge adds kernel frames through bpf_obj_free_fields() and
+ * __bpf_obj_drop_impl(). Keep the bound deliberately small because object
+ * destruction can itself run below a BPF call chain. A final pointee without
+ * special fields is not present in the struct metadata table and adds only a
+ * non-recursing drop.
  */
 #define BTF_MAX_OWNERSHIP_DEPTH 8
 
-- 
2.53.0


  parent reply	other threads:[~2026-09-05  9:07 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-05  9:07 [PATCH bpf-next v1 0/3] Fix acyclic ownership checks Kumar Kartikeya Dwivedi
2026-09-05  9:07 ` [PATCH bpf-next v1 1/3] bpf: Validate graph ownership with a bounded walk Kumar Kartikeya Dwivedi
2026-09-05 21:29   ` Alexei Starovoitov
2026-09-05  9:07 ` Kumar Kartikeya Dwivedi [this message]
2026-09-05  9:07 ` [PATCH bpf-next v1 3/3] selftests/bpf: Check local object ownership depth 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=20260905090750.4064411-3-memxor@gmail.com \
    --to=memxor@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=npc@anthropic.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.