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>
index | next in thread | raw e-mail
>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
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108262114.f7QLEJv24418>
