knlsit_cleardel() panic

From: Kostik Belousov <kostikbel_at_gmail.com>
Date: Sun, 2 Mar 2008 17:25:23 +0200
Hi,

The panic below was already reported, but now I got it on my desktop
and was able to investigate further.

#5  0xc06daf36 in trap (frame=0xe8093b1c)
    at /usr/bsd/src/sys/i386/i386/trap.c:490
#6  0xc06c0b4b in calltrap () at /usr/bsd/src/sys/i386/i386/exception.s:139
#7  0xc0493968 in knlist_cleardel (knl=0xcabec128, td=0x0, islocked=1, 
    killkn=0) at atomic.h:149
#8  0xc04f520c in pipeclose (cpipe=0xcabec0b8)
    at /usr/bsd/src/sys/kern/sys_pipe.c:1508
#9  0xc04f5320 in pipe_close (fp=0xc5ce8630, td=0xcac01aa0)
    at /usr/bsd/src/sys/kern/sys_pipe.c:1425
#10 0xc0489442 in fdrop (fp=0xc5ce8630, td=0xcac01aa0) at file.h:297
#11 0xc048accf in closef (fp=0xc5ce8630, td=0xcac01aa0)
    at /usr/bsd/src/sys/kern/kern_descrip.c:1958
#12 0xc048b1ff in kern_close (td=0xcac01aa0, fd=10)
    at /usr/bsd/src/sys/kern/kern_descrip.c:1054
#13 0xc048b2da in close (td=0xcac01aa0, uap=0xe8093cfc)
    at /usr/bsd/src/sys/kern/kern_descrip.c:1006
---Type <return> to continue, or q <return> to quit---
#14 0xc06da865 in syscall (frame=0xe8093d38)
    at /usr/bsd/src/sys/i386/i386/trap.c:1035
#15 0xc06c0bb0 in Xint0x80_syscall ()
    at /usr/bsd/src/sys/i386/i386/exception.s:196

At the frame 8, we have
(kgdb) p/x *(knl->kl_list->slh_first)
$9 = {kn_link = {sle_next = 0x0}, kn_selnext = {sle_next = 0x0},
  kn_knlist = 0x0, kn_tqe = {tqe_next = 0xc58de484, tqe_prev = 0xc5e9ab20},
  kn_kq = 0x0, kn_kevent = {ident = 0x0, filter = 0x0, flags = 0x0,
    fflags = 0x0, data = 0x0, udata = 0x0}, kn_status = 0x20,
  kn_sfflags = 0x0, kn_sdata = 0x0, kn_ptr = {p_fp = 0x0, p_proc = 0x0,
    p_aio = 0x0, p_lio = 0x0}, kn_fop = 0x0, kn_hook = 0x0}

The knote is KN_MARKER, and the kn_kq is NULL. The result is that KQ_LOCK
in the knlist_cleardel()::SLIST_FOREACH_SAFE() loop dereferences NULL and
panics.

Does the following change makes any sense?

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 9ac661c..31ac77a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
_at__at_ -1169,6 +1169,7 _at__at_ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
 		goto done_nl;
 	}
 	marker->kn_status = KN_MARKER;
+	marker->kn_kq = kq;
 	KQ_LOCK(kq);
 	goto start;
 
_at__at_ -1742,7 +1743,8 _at__at_ again:		/* need to reacquire lock since we have dropped it */
 	SLIST_FOREACH_SAFE(kn, &knl->kl_list, kn_selnext, kn2) {
 		kq = kn->kn_kq;
 		KQ_LOCK(kq);
-		if ((kn->kn_status & KN_INFLUX)) {
+		if ((kn->kn_status & KN_INFLUX) ||
+		    (kn->kn_status & KN_MARKER)) {
 			KQ_UNLOCK(kq);
 			continue;
 		}
_at__at_ -1764,7 +1766,8 _at__at_ again:		/* need to reacquire lock since we have dropped it */
 		kn = SLIST_FIRST(&knl->kl_list);
 		kq = kn->kn_kq;
 		KQ_LOCK(kq);
-		KASSERT(kn->kn_status & KN_INFLUX,
+		KASSERT((kn->kn_status & KN_INFLUX) ||
+			(kn->kn_status & KN_MARKER),
 		    ("knote removed w/o list lock"));
 		knl->kl_unlock(knl->kl_lockarg);
 		kq->kq_state |= KQ_FLUXWAIT;

Received on Sun Mar 02 2008 - 14:25:39 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:28 UTC