Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Jan 2003 15:40:52 +0100 (CET)
From:      Hartmut Brandt <brandt@fokus.fraunhofer.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        sparc@FreeBSD.org
Subject:   kern/47408: td_wmesg not cleared leads to panic when doing 'ps ax'
Message-ID:  <200301231440.h0NEeqZ9000639@catssrv.fokus.gmd.de>

next in thread | raw e-mail | index | archive | help

>Number:         47408
>Category:       kern
>Synopsis:       td_wmesg not cleared leads to panic when doing 'ps ax'
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 23 06:50:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Hartmut Brandt
>Release:        FreeBSD 5.0-CURRENT sparc64
>Organization:
>Environment:
System: FreeBSD catssrv.fokus.gmd.de 5.0-CURRENT FreeBSD 5.0-CURRENT #17: Thu Jan 23 15:26:01 CET 2003 hbb@catssrv.fokus.gmd.de:/opt/obj/usr/src/sys/CATSSRV sparc64


	
>Description:

The field td_wmesg of struct thread holds a pointer to a constant string
and is set, when a thread calls either msleep or waits on a condition variable.
When the thread continues, this fields is not cleared. When the msleep or
cv_wait was called from a module, that is unloaded, the pointer in td_wmesg
appears to become invalid. When now someone retrieves the process table via
sysctl, then the kernel handler for this sysctl may access the now invalid
pointer. On the SPARC this leads to a panic. i386 probably simply uses an
invalid string (at least I have not seen that panic there).
	
>How-To-Repeat:

On the sparc:

	1. load an interface driver that uses cv_wait or msleep.
	2. unload the driver via kldunload
	3. ps ax

leads to an immediate crash.

	
>Fix:

Apply the attached patch. This sets td_wmesg to NULL when an msleep exits
either via the timeout or because of wakeup. It sets also td_wmesg to NULL
when a thread is remove from the wait queue of a condition variable.

Index: sys/kern/kern_condvar.c
===================================================================
RCS file: /home/cvs/freebsd/src/sys/kern/kern_condvar.c,v
retrieving revision 1.35
diff -c -r1.35 kern_condvar.c
*** sys/kern/kern_condvar.c	28 Dec 2002 01:23:07 -0000	1.35
--- sys/kern/kern_condvar.c	23 Jan 2003 14:31:51 -0000
***************
*** 535,540 ****
--- 535,541 ----
  	if ((cvp = td->td_wchan) != NULL && td->td_flags & TDF_CVWAITQ) {
  		TAILQ_REMOVE(&cvp->cv_waitq, td, td_slpq);
  		td->td_flags &= ~TDF_CVWAITQ;
+ 		td->td_wmesg = NULL;
  		TD_CLR_ON_SLEEPQ(td);
  	}
  }
Index: sys/kern/kern_synch.c
===================================================================
RCS file: /home/cvs/freebsd/src/sys/kern/kern_synch.c,v
retrieving revision 1.209
diff -c -r1.209 kern_synch.c
*** sys/kern/kern_synch.c	28 Dec 2002 01:23:07 -0000	1.209
--- sys/kern/kern_synch.c	23 Jan 2003 14:31:51 -0000
***************
*** 330,335 ****
--- 330,336 ----
  		TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_slpq);
  		TD_CLR_ON_SLEEPQ(td);
  		td->td_flags |= TDF_TIMEOUT;
+ 		td->td_wmesg = NULL;
  	} else {
  		td->td_flags |= TDF_TIMOFAIL;
  	}
***************
*** 374,379 ****
--- 375,381 ----
  	if (TD_ON_SLEEPQ(td)) {
  		TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_slpq);
  		TD_CLR_ON_SLEEPQ(td);
+ 		td->td_wmesg = NULL;
  	}
  	mtx_unlock_spin(&sched_lock);
  }
	


>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200301231440.h0NEeqZ9000639>