[Bug 293382] Dead lock and kernel crash around closefp_impl
- In reply to: bugzilla-noreply_a_freebsd.org: "[Bug 293382] Dead lock and kernel crash around closefp_impl"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 30 Mar 2026 12:13:32 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=293382
--- Comment #29 from Konstantin Belousov <kib@FreeBSD.org> ---
(In reply to Paul from comment #28)
The saved knote has ident = 138904, while stack trace shows fd=544408.
This should not happen, the file descriptor must be same as the knote which
we find on the descriptor-indexed list.
Suppose that the debugging info is correct. This means that the knote existed
on the list for both 544408 and 138904? This could be if e.g. both heads
pointed
to the knote. Then if fd 138904 got the knote already removed or even not
found
on that list (as recorded by the stack trace), it is freed, but the pointer
on the list 544408 is dandling. Then we get the situation in the panic.
If the speculation above holds, then somehow we manage to insert same knote
into two different fd's lists. Again, I do not understand how could this
happen.
I modified the debugging patch to check just that, that knotes are never
inserted
twice into kn_link.
Could you run HEAD with only the patch below applied, please? No need to apply
any of my previous patches, but do update to the latest HEAD since Mark already
committed his fix. I am interested if you hit the added panics.
commit 8b90be098a85975dc437c53294987c0d7106fcf9
Author: Konstantin Belousov <kib@FreeBSD.org>
Date: Wed Mar 25 03:47:59 2026 +0200
debug
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 1a719f7c945c..7d99f00eeb8c 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -229,6 +229,12 @@ static const struct filterops user_filtops = {
.f_copy = knote_triv_copy,
};
+struct eknote {
+ struct knote k;
+ struct knote c;
+ int on_kn_link;
+};
+
static uma_zone_t knote_zone;
static unsigned int __exclusive_cache_line kq_ncallouts;
static unsigned int kq_calloutmax = 4 * 1024;
@@ -2887,6 +2893,9 @@ knote_attach(struct knote *kn, struct kqueue *kq)
return (ENOMEM);
list = &kq->kq_knhash[KN_HASH(kn->kn_id, kq->kq_knhashmask)];
}
+ if (atomic_fetchadd_int(&__containerof(kn, struct eknote,
+ k)->on_kn_link, 1) != 0)
+ panic("Double-linking knote %p", kn);
SLIST_INSERT_HEAD(list, kn, kn_link);
return (0);
}
@@ -2928,8 +2937,11 @@ knote_drop_detached(struct knote *kn, struct thread *td)
else
list = &kq->kq_knhash[KN_HASH(kn->kn_id, kq->kq_knhashmask)];
- if (!SLIST_EMPTY(list))
- SLIST_REMOVE(list, kn, knote, kn_link);
+ if (atomic_fetchadd_int(&__containerof(kn, struct eknote,
+ k)->on_kn_link, -1) != 1)
+ panic("removal of double-linked knote %p", kn);
+ SLIST_REMOVE(list, kn, knote, kn_link);
+
if (kn->kn_status & KN_QUEUED)
knote_dequeue(kn);
KQ_UNLOCK_FLUX(kq);
@@ -2974,8 +2986,8 @@ static void
knote_init(void *dummy __unused)
{
- knote_zone = uma_zcreate("KNOTE", sizeof(struct knote), NULL, NULL,
- NULL, NULL, UMA_ALIGN_PTR, 0);
+ knote_zone = uma_zcreate("KNOTE", sizeof(struct eknote), NULL, NULL,
+ NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
ast_register(TDA_KQUEUE, ASTR_ASTF_REQUIRED, 0, ast_kqueue);
prison0.pr_klist = knlist_alloc(&prison0.pr_mtx);
}
@@ -2984,15 +2996,24 @@ SYSINIT(knote, SI_SUB_PSEUDO, SI_ORDER_ANY, knote_init,
NULL);
static struct knote *
knote_alloc(int mflag)
{
+ struct eknote *e;
- return (uma_zalloc(knote_zone, mflag | M_ZERO));
+ e = uma_zalloc(knote_zone, mflag);
+ memset(e, 0, sizeof(*e));
+ return (&e->k);
}
static void
knote_free(struct knote *kn)
{
+ struct eknote *e;
- uma_zfree(knote_zone, kn);
+ if (kn == NULL)
+ return;
+ e = __containerof(kn, struct eknote, k);
+ e->c = e->k;
+ memset(&e->k, 0xdeadc0de, sizeof(e->k));
+ uma_zfree(knote_zone, e);
}
/*
--
You are receiving this mail because:
You are the assignee for the bug.