Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Aug 2001 07:14:19 +1000 (EST)
From:      Peter Jeremy <peter.jeremy@alcatel.com.au>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/30112: Inadequate validation of kernel message buffer (msgbufp)
Message-ID:  <200108262114.f7QLEJv24418@gsmx07.alcatel.com.au>

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

>Number:         30112
>Category:       kern
>Synopsis:       Inadequate validation of kernel message buffer (msgbufp)
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 26 14:20:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Peter Jeremy
>Release:        FreeBSD 4.4-RC i386
>Organization:
Alcatel Australia Limited
>Environment:
System: FreeBSD cirb503493.alcatel.com.au 4.4-RC FreeBSD 4.4-RC #4: Sun Aug 26 20:00:30 EST 2001 root@:/usr/obj/usr/src/sys/pj1592 i386

	Compaq Armada 1592DT
	running -STABLE from cvs-cur.7507 (~Aug 25 2200)

>Description:
	Rebooting to multi-user mode or viewing machdep.msgbuf would
	consistently panic the machine in slow_copyout() (part of i586
	generic_copyout()).  The crash dump showed that msgbufp->msg_bufr
	contained garbage (though the other fields appeared sane).

	The code in msgbufinit() will reuse an existing message buffer
	(preserving the contents across crashes where possible) but only
	checks the magic number and buffer pointer for validity.  The
	read index, write index and size are not validated if the buffer
	is reused.  This means that should these fields become corrupt,
 	the kernel can access random memory when reading or writing the
	message buffer.

	Whilst it is possible to wipe a corrupted message buffer with
	the sysctl kern.msgbuf_clear, the kernel should better validate
	structures that it is trusting.

>How-To-Repeat:
	(This is a possible scenario - I haven't actually tried this).
	Using a debugger, set msgbufp->msg_bufr to a nonsense value
	and the read the message buffer.  The system will panic and
	upon rebooting will again panic when syslogd starts.

>Fix:
	The following patch better validates an existing msgbufp, but
	does not further check it.  It may be reasonable to add some
	KASSERT()s in (eg) msgaddchar(), but it would be necessary to
	ensure that triggering the KASSERT() would not lead to nested
	panic()s [msgbufp is corrupt, triggering a panic(), which logs
	the panic via msgaddchar() which detects that msgbufp is
	corrupt and panics()].

	Note that whilst this patch is running, I had manually cleared
	the corruption before rebooting, so it has not been tested on
	a corrupt msgbufp.

Index: subr_prf.c
===================================================================
RCS file: /usr/ncvs/src/sys/kern/subr_prf.c,v
retrieving revision 1.61.2.2
diff -u -r1.61.2.2 subr_prf.c
--- subr_prf.c	2001/08/08 22:31:16	1.61.2.2
+++ subr_prf.c	2001/08/26 04:45:47
@@ -836,13 +836,17 @@
 {
 	char *cp;
 	static struct msgbuf *oldp = NULL;
+	unsigned int msg_size;
 
 	cp = (char *)ptr;
 	msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp));
-	if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) {
+	msg_size = (char *)msgbufp - cp;
+	if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp ||
+	    msgbufp->msg_size != msg_size || msgbufp->msg_bufx >= msg_size ||
+	    msgbufp->msg_bufr >= msg_size) {
 		bzero(cp, size);
 		msgbufp->msg_magic = MSG_MAGIC;
-		msgbufp->msg_size = (char *)msgbufp - cp;
+		msgbufp->msg_size = msg_size;
 		msgbufp->msg_ptr = cp;
 	}
 	if (msgbufmapped && oldp != msgbufp)
>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?200108262114.f7QLEJv24418>