From: chenyuan_fl@163.com
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Yuan Chen <chenyuan@kylinos.cn>
Subject: [PATCH bpf-next 1/2] bpf: Cancel special fields in resizable hashtab on recycle
Date: Tue, 11 Aug 2026 17:55:30 +0800 [thread overview]
Message-ID: <20260811095531.3294167-2-chenyuan_fl@163.com> (raw)
In-Reply-To: <20260811095531.3294167-1-chenyuan_fl@163.com>
From: Yuan Chen <chenyuan@kylinos.cn>
rhtab_delete_elem() and rhtab_map_update_existing() eagerly call
bpf_obj_free_fields() when an element is deleted or its value is
replaced. This runs kptr destructors (and unpins uptrs, frees list/rbtree
roots) in the caller's execution context, which is unsafe for BPF
programs running in NMI context (e.g. perf_event programs attached to
hardware PMU overflows): referenced kptr destructors may take locks or
otherwise cannot run in NMI.
Commit a3a81d247651 ("bpf: Cancel special fields on map value recycle")
switched the hash map and array recycle paths to bpf_obj_cancel_fields(),
which only cancels NMI-safe fields (timer, workqueue, task_work), but it
missed the resizable hashtab. rhtab_map_update_existing() even documents
the intended "cancel" semantics while still calling bpf_obj_free_fields().
Fix by cancelling only NMI-safe fields on rhtab update/delete and leaving
referenced kptrs (and other fields requiring full destruction) attached
to the recycled element, to be destroyed by rhtab_mem_dtor() when the
element is eventually freed. This matches the hash map semantics and
keeps the element's kptr reference accounting balanced: the reference
stays owned by the element and is released exactly once by the final
destruction path.
Verified with a selftest (perf_event NMI program overwriting a rhtab
element that holds a referenced task kptr): before this patch the NMI
update releases the kptr and the subsequent probe observes NULL in the
slot; after the patch the kptr is inherited and the probe observes it
non-NULL.
Fixes: a3a81d247651 ("bpf: Cancel special fields on map value recycle")
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
kernel/bpf/hashtab.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 9f394e1aa2e8..70fa1e1b4b00 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -2865,14 +2865,23 @@ static int rhtab_map_alloc_check(union bpf_attr *attr)
return htab_map_alloc_check(attr);
}
-static void rhtab_check_and_free_fields(struct bpf_rhtab *rhtab,
- struct rhtab_elem *elem)
+static void rhtab_cancel_fields(struct bpf_rhtab *rhtab,
+ struct rhtab_elem *elem)
{
if (IS_ERR_OR_NULL(rhtab->map.record))
return;
- bpf_obj_free_fields(rhtab->map.record,
- rhtab_elem_value(elem, rhtab->map.key_size));
+ /*
+ * Only cancel NMI-safe fields (timer, workqueue, task_work) here.
+ * kptr/uptr/list/rbtree destruction must not run from arbitrary BPF
+ * execution contexts (e.g. NMI), so leave those fields attached to
+ * the recycled element and let rhtab_mem_dtor() destroy them once the
+ * element is eventually freed. This matches the hash map semantics
+ * introduced by a3a81d247651 ("bpf: Cancel special fields on map value
+ * recycle").
+ */
+ bpf_map_free_internal_structs(&rhtab->map,
+ rhtab_elem_value(elem, rhtab->map.key_size));
}
static void rhtab_mem_dtor(void *obj, void *ctx)
@@ -2964,8 +2973,8 @@ static int rhtab_delete_elem(struct bpf_rhtab *rhtab, struct rhtab_elem *elem, v
rhtab_read_elem_value(&rhtab->map, copy, elem, flags);
check_and_init_map_value(&rhtab->map, copy);
}
- /* Release internal structs: kptr, bpf_timer, task_work, wq */
- rhtab_check_and_free_fields(rhtab, elem);
+ /* Cancel NMI-safe fields; full destruction happens in rhtab_mem_dtor */
+ rhtab_cancel_fields(rhtab, elem);
bpf_mem_cache_free_rcu(&rhtab->ma, elem);
return 0;
}
@@ -3024,10 +3033,11 @@ static long rhtab_map_update_existing(struct bpf_map *map, struct rhtab_elem *el
* BPF_F_LOCK, matching arraymap semantics.
*
* copy_map_value() skips special-field offsets, so old timers/
- * kptrs/etc. still sit in the slot. Cancel them after the copy
- * to match arraymap's update semantics.
+ * kptrs/etc. still sit in the slot. Cancel the NMI-safe ones after
+ * the copy to match arraymap's update semantics; referenced kptrs
+ * stay attached and are destroyed by rhtab_mem_dtor().
*/
- rhtab_check_and_free_fields(rhtab, elem);
+ rhtab_cancel_fields(rhtab, elem);
return 0;
}
--
2.54.0
next prev parent reply other threads:[~2026-08-11 9:56 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 9:55 [PATCH bpf-next 0/2] bpf: Cancel special fields in resizable hashtab on recycle chenyuan_fl
2026-08-11 9:55 ` chenyuan_fl [this message]
2026-08-11 10:50 ` [PATCH bpf-next 1/2] " bot+bpf-ci
2026-08-11 9:55 ` [PATCH bpf-next 2/2] selftests/bpf: Test rhtab kptr recycle from NMI context chenyuan_fl
2026-08-11 11:08 ` bot+bpf-ci
2026-08-11 14:22 ` [PATCH bpf-next 0/2] bpf: Cancel special fields in resizable hashtab on recycle Kumar Kartikeya Dwivedi
2026-08-24 14:36 ` [PATCH bpf-next v2 0/4] " chenyuan_fl
2026-08-24 14:36 ` [PATCH 1/4] " chenyuan_fl
2026-08-24 15:00 ` sashiko-bot
2026-08-24 15:42 ` bot+bpf-ci
2026-08-24 16:15 ` Mykyta Yatsenko
2026-09-01 6:28 ` [PATCH bpf-next v3 0/4] " chenyuan_fl
2026-09-01 6:28 ` [PATCH bpf-next v3 1/4] " chenyuan_fl
2026-09-01 6:49 ` sashiko-bot
2026-09-01 7:37 ` bot+bpf-ci
2026-09-01 16:57 ` Mykyta Yatsenko
2026-09-01 6:28 ` [PATCH bpf-next v3 2/4] bpf: Fix use-after-free of program BTF in mem-alloc destructor chenyuan_fl
2026-09-01 17:10 ` Mykyta Yatsenko
2026-09-01 6:28 ` [PATCH bpf-next v3 3/4] selftests/bpf: Test rhtab kptr recycle from NMI context chenyuan_fl
2026-09-01 6:40 ` sashiko-bot
2026-09-01 7:37 ` bot+bpf-ci
2026-09-01 6:28 ` [PATCH bpf-next v3 4/4] selftests/bpf: Test rhtab special-field combinations chenyuan_fl
2026-09-01 6:41 ` sashiko-bot
2026-09-01 7:37 ` bot+bpf-ci
2026-09-04 10:49 ` [PATCH bpf-next v3 0/4] bpf: Cancel special fields in resizable hashtab on recycle Kumar Kartikeya Dwivedi
2026-08-24 14:36 ` [PATCH 2/4] bpf: Fix use-after-free of program BTF in mem-alloc destructor chenyuan_fl
2026-08-24 15:17 ` sashiko-bot
2026-08-24 15:42 ` bot+bpf-ci
2026-08-24 14:36 ` [PATCH 3/4] selftests/bpf: Test rhtab kptr recycle from NMI context chenyuan_fl
2026-08-24 15:28 ` sashiko-bot
2026-08-24 15:42 ` bot+bpf-ci
2026-08-24 14:36 ` [PATCH 4/4] selftests/bpf: Test rhtab special-field combinations chenyuan_fl
2026-08-24 15:40 ` sashiko-bot
2026-08-24 15:42 ` bot+bpf-ci
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=20260811095531.3294167-2-chenyuan_fl@163.com \
--to=chenyuan_fl@163.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=chenyuan@kylinos.cn \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=martin.lau@linux.dev \
--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.