summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-06-09 21:23:12 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-06-09 21:23:12 -0700
commit1fed2e47fac582e824f77f68722a8a13820e58e2 (patch)
tree703f21d578314c1ee115b1c9a44ee754bdbd90cf /include/linux
parent140fa23df957b51385aa847986d44ad7f59b0563 (diff)
parent2e7c6cb4d8437a2fe7cd95aac7ca53d7eb05e9f4 (diff)
Merge branch 'fix-kptr-dtor-deadlock'
Kumar Kartikeya Dwivedi says: ==================== Fix kptr dtor deadlock Referenced kptr destruction can run from tracing/NMI contexts through bpf_obj_drop() and map value update/delete paths, reaching NMI-unsafe special field teardown and deadlocks. Justin reported the issue and iterated on fixes in [0]-[2], and also confirmed the bpf_obj_drop() reproducer in [3]. This series rejects unsafe obj drops from non-iterator tracing programs, limits map value recycle to NMI-safe field cancellation, and adds focused selftests for the obj_drop(), NMI delete, and recycle teardown cases. See patches for details. [0]: https://lore.kernel.org/bpf/20260505150851.3090688-1-utilityemal77@gmail.com [1]: https://lore.kernel.org/bpf/20260507175453.1140400-1-utilityemal77@gmail.com [2]: https://lore.kernel.org/bpf/20260519011450.1144935-1-utilityemal77@gmail.com [3]: https://lore.kernel.org/bpf/agyG3eQwgmoJwmj2@suesslenovo Changelog: ---------- v2 -> v3 v2: https://lore.kernel.org/bpf/20260609093719.2858096-1-memxor@gmail.com * Replace bpf_obj_cancel_fields() to use bpf_map_free_internal_structs(). (Mykyta) * Fix CI failures. v1 -> v2 v1: https://lore.kernel.org/bpf/20260608144841.1732406-1-memxor@gmail.com * Drop is_tracing_prog_type() fix due to compat breakage, revisit separately. * Rework bpf_obj_drop() fix to additionally reject non-iter tracing progs. ==================== Link: https://patch.msgid.link/20260609202548.3571690-1-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bpf.h30
1 files changed, 30 insertions, 0 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 62bba7a4876f..56f5da2b437f 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -492,6 +492,35 @@ static inline bool btf_record_has_field(const struct btf_record *rec, enum btf_f
return rec->field_mask & type;
}
+static inline bool btf_field_is_nmi_safe(enum btf_field_type type)
+{
+ switch (type) {
+ case BPF_SPIN_LOCK:
+ case BPF_RES_SPIN_LOCK:
+ case BPF_TIMER:
+ case BPF_WORKQUEUE:
+ case BPF_TASK_WORK:
+ case BPF_KPTR_UNREF:
+ case BPF_REFCOUNT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool btf_record_has_nmi_unsafe_fields(const struct btf_record *rec)
+{
+ int i;
+
+ if (IS_ERR_OR_NULL(rec))
+ return false;
+ for (i = 0; i < rec->cnt; i++) {
+ if (!btf_field_is_nmi_safe(rec->fields[i].type))
+ return true;
+ }
+ return false;
+}
+
static inline void bpf_obj_init(const struct btf_record *rec, void *obj)
{
int i;
@@ -2688,6 +2717,7 @@ bool btf_record_equal(const struct btf_record *rec_a, const struct btf_record *r
void bpf_obj_free_timer(const struct btf_record *rec, void *obj);
void bpf_obj_free_workqueue(const struct btf_record *rec, void *obj);
void bpf_obj_free_task_work(const struct btf_record *rec, void *obj);
+void bpf_obj_cancel_fields(struct bpf_map *map, void *obj);
void bpf_obj_free_fields(const struct btf_record *rec, void *obj);
void __bpf_obj_drop_impl(void *p, const struct btf_record *rec, bool percpu);