From jeremyp@gsmx07.alcatel.com.au  Sun Aug 26 14:14:32 2001
Return-Path: <jeremyp@gsmx07.alcatel.com.au>
Received: from netau1.alcanet.com.au (ntp.alcanet.com.au [203.62.196.27])
	by hub.freebsd.org (Postfix) with ESMTP id C731E37B414
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 26 Aug 2001 14:14:30 -0700 (PDT)
	(envelope-from jeremyp@gsmx07.alcatel.com.au)
Received: from mfg1.cim.alcatel.com.au (mfg1.cim.alcatel.com.au [139.188.23.1])
	by netau1.alcanet.com.au (8.9.3 (PHNE_22672)/8.9.3) with ESMTP id HAA28996
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 27 Aug 2001 07:14:28 +1000 (EST)
Received: from gsmx07.alcatel.com.au by cim.alcatel.com.au
 (PMDF V5.2-32 #37641) with ESMTP id <01K7MC2ZWVHSVFE1MI@cim.alcatel.com.au>
 for FreeBSD-gnats-submit@freebsd.org; Mon, 27 Aug 2001 07:14:13 +1000
Received: (from jeremyp@localhost)	by gsmx07.alcatel.com.au (8.11.1/8.11.1)
 id f7QLEJv24418; Mon, 27 Aug 2001 07:14:19 +1000 (EST envelope-from jeremyp)
Message-Id: <200108262114.f7QLEJv24418@gsmx07.alcatel.com.au>
Date: Mon, 27 Aug 2001 07:14:19 +1000 (EST)
From: Peter Jeremy <peter.jeremy@alcatel.com.au>
Reply-To: Peter Jeremy <peter.jeremy@alcatel.com.au>
To: FreeBSD-gnats-submit@freebsd.org
Subject: Inadequate validation of kernel message buffer (msgbufp)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         30112
>Category:       kern
>Synopsis:       Inadequate validation of kernel message buffer (msgbufp)
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 26 14:20:00 PDT 2001
>Closed-Date:    Tue Nov 13 14:40:03 PST 2001
>Last-Modified:  Tue Nov 13 14:51:19 PST 2001
>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:
State-Changed-From-To: open->closed 
State-Changed-By: iedowse 
State-Changed-When: Tue Nov 13 14:40:03 PST 2001 
State-Changed-Why:  

This was fixed in revision 1.73 of subr_prf.c with a change that 
is very similar to the patch in this PR. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=30112 
>Unformatted:
