Subject: kern/7386: msgrcv(3) will cause buffer over-run in a certain condition
To: None <gnats-bugs@NetBSD.org>
From: None <futatuki@fureai.or.jp>
List: netbsd-bugs
Date: 04/14/1999 11:06:00
>Number:         7386
>Category:       kern
>Synopsis:       msgrcv(3) will cause buffer over-run in a certain condition
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 14 11:05:00 1999
>Last-Modified:
>Originator:     Yasuhito FUTATSUKI
>Organization:
>Release:        FreeBSD 2.2.7-RELEASE i386
>Environment:

Those NetBSD system which uses 

/*      $NetBSD: sysv_msg.c,v 1.24 1998/10/21 22:24:28 tron Exp $       */

version of src/sys/kern/sysv_msg.c

>Description:

msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) will copy larger size of
message data than specified by msgsz if

  1. msgsz is larger than `msgssz', and
  2. msgsz is not multiples of `msgssz'

where msgssz is the size of message segment in bytes.

I found this problem on FreeBSD, but the code for system V message
handling derived from NetBSD, so I read the code for this feature
and found there is the problem on NetBSD also.

>How-To-Repeat:

Assume msgssz is 8, message que of id msgid is accessable,
a message of type msgtype and size 20 bytes was sent, then

  struct {
    long mtype;
    char mtext[20];
    long some_data;
  } mymsg;

  msgrcv(msqid, (void*)mymsg, 20, msgtype, 0);

will crash mymsg.some_data .

>Fix:
	
Apply following patch to src/sys/kern/sysv_msg.c :

BEGIN --- cut here --- --- cut here --- --- cut here ---
*** sysv_msg.c.dist	Wed Apr 14 16:49:14 1999
--- sysv_msg.c	Wed Apr 14 16:57:25 1999
***************
*** 847,856 ****
  	for (len = 0; len < msgsz; len += msginfo.msgssz) {
  		size_t tlen;
  
! 		if (msgsz > msginfo.msgssz)
  			tlen = msginfo.msgssz;
  		else
! 			tlen = msgsz;
  		if (next <= -1)
  			panic("next too low #3");
  		if (next >= msginfo.msgseg)
--- 847,856 ----
  	for (len = 0; len < msgsz; len += msginfo.msgssz) {
  		size_t tlen;
  
! 		if (msgsz - len > msginfo.msgssz)
  			tlen = msginfo.msgssz;
  		else
! 			tlen = msgsz - len;
  		if (next <= -1)
  			panic("next too low #3");
  		if (next >= msginfo.msgseg)
END --- cut here --- --- cut here --- --- cut here ---
>Audit-Trail:
>Unformatted: