From owner-freebsd-bugs Sun Aug 26 14:20: 9 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 7E2B637B40C for ; Sun, 26 Aug 2001 14:20:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.4/8.11.4) id f7QLK1O53643; Sun, 26 Aug 2001 14:20:01 -0700 (PDT) (envelope-from gnats) Received: from netau1.alcanet.com.au (ntp.alcanet.com.au [203.62.196.27]) by hub.freebsd.org (Postfix) with ESMTP id C731E37B414 for ; 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 ; 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 Reply-To: Peter Jeremy To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.113 Subject: kern/30112: Inadequate validation of kernel message buffer (msgbufp) Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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