Subject: kern/1891: statically-sized message buffer wastes space on many ports
To: None <gnats-bugs@gnats.netbsd.org>
From: Chris G. Demetriou <cgd@NetBSD.ORG>
List: netbsd-bugs
Date: 01/04/1996 23:36:31
>Number:         1891
>Category:       kern
>Synopsis:       kernel msgbuf has fixed size; pages can be partially wasted.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Jan  5 00:05:02 1996
>Last-Modified:
>Originator:     Chris G. Demetriou
>Organization:
Kernel Hackers 'r' Us
>Release:        NetBSD-current as of January 4, 1996
>Environment:
System: NetBSD sun-lamp.pc.cs.cmu.edu 1.1A NetBSD 1.1A (SUN_LAMP) #19: Thu Jan 4 20:42:03 EST 1996 cgd@sun-lamp.pc.cs.cmu.edu:/usr/src/sys/arch/i386/compile/SUN_LAMP i386


>Description:
	The current definition of the kernel message buffer is fixed at
	4k in size.  This is annoying on machines with a hardware page
	sizes > 4k, because:
		(1) it's relatively hard to make use of the rest of the
		    page being used for the message buffer, and
		(2) given that you're wasting the space, having a too-small
		    dmesg buffer is _very_ annoying, if your dmesg output
		    is the only easy way for you to get crash information.

	Similarly, given the current definition of msgbuf, you can't
	devote multiple pages to the message buffer, even if you want to.
	System developers might want a larger (potentially much larger;
	i'd not mind 32k...) message buffer, and it might be nice for ports
	to provide it as a compile-time option.

>How-To-Repeat:
	on a machine that keeps message buffer output from one boot to the
	next (which, as far as i can tell, is _not_ most pc's; they
	clear memory):

	reboot
	reboot again
	reboot again

	and note that you probably don't have all three boots' dmesg output
	available with 'dmesg.'  If you're on a machine with an 8k page size,
	look at the source to see if a full page is being used for dmesg stuff,
	but note that never more than 4k (minus a few bytes, actually) of
	message buffer text is available.

>Fix:
	I've included diffs to implement a variable-size message buffer, below.
	The diffs deal with the machine-specific changes for the i386, but
	I didn't do any of the other ports.  (Actually, I did the Alpha, too,
	but those changes are being committed to my NetBSD/Alpha tree
	locally, until they're accepted into the master sources, at which
	point i will update the -current NetBSD/Alpha sources.)

	With these diffs, old 'dmesg' and 'syslogd' binaries will continue
	running, though old 'dmesg' binaries will output a few bytes of
	junk at the start of the buffer, and will miss a few bytes at the
	end of the buffer.

	Once the changes have been applied, new 'syslogd' binaries should
	run with old kernels with few side effects, but new 'dmesg'
	binaries may or may not work properly with old kernels.

	These diffs also rename the 'msgbuf' struct to 'kern_msgbuf', so
	that PR 1725 may be fixed more easily.

Index: lib/libc/gen/sysctl.3
===================================================================
RCS file: /a/cvsroot/src/lib/libc/gen/sysctl.3,v
retrieving revision 1.7
diff -c -r1.7 sysctl.3
*** sysctl.3	1995/09/30 07:03:54	1.7
--- sysctl.3	1996/01/05 03:08:57
***************
*** 243,248 ****
--- 243,249 ----
  .It KERN\_MAXVNODES	integer	yes
  .It KERN\_MAX\_CANON	integer	no
  .It KERN\_MAX\_INPUT	integer	no
+ .It KERN\_MSGBUFSIZE	integer	no
  .It KERN\_NAME\_MAX	integer	no
  .It KERN\_NGROUPS	integer	no
  .It KERN\_NO\_TRUNC	integer	no
***************
*** 312,317 ****
--- 313,320 ----
  .It Li KERN_MAX_INPUT
  The minimum maximum number of bytes for which space is available in
  a terminal input queue.
+ .It Li KERN_MSGBUFSIZE
+ The maximum number of characters that the kernel message buffer can hold.
  .It Li KERN_NAME_MAX
  The maximum number of bytes in a file name.
  .It Li KERN_NGROUPS
Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /a/cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.183
diff -c -r1.183 machdep.c
*** machdep.c	1996/01/04 22:22:01	1.183
--- machdep.c	1996/01/05 03:09:15
***************
*** 122,129 ****
  int	boothowto;
  int	cpu_class;
  
! struct	msgbuf *msgbufp;
! int	msgbufmapped;
  
  vm_map_t buffer_map;
  
--- 122,128 ----
  int	boothowto;
  int	cpu_class;
  
! caddr_t	msgbufaddr;
  
  vm_map_t buffer_map;
  
***************
*** 154,164 ****
  	 * Initialize error message buffer (at end of core).
  	 */
  	/* avail_end was pre-decremented in pmap_bootstrap to compensate */
! 	for (i = 0; i < btoc(sizeof(struct msgbuf)); i++)
! 		pmap_enter(pmap_kernel(),
! 		    (vm_offset_t)((caddr_t)msgbufp + i * NBPG),
! 		    avail_end + i * NBPG, VM_PROT_ALL, TRUE);
! 	msgbufmapped = 1;
  
  	printf(version);
  	identifycpu();
--- 153,161 ----
  	 * Initialize error message buffer (at end of core).
  	 */
  	/* avail_end was pre-decremented in pmap_bootstrap to compensate */
! 	pmap_enter(pmap_kernel(), (vm_offset_t)msgbufaddr, avail_end,
! 	    VM_PROT_ALL, TRUE);
! 	initmsgbuf(msgbufaddr, NBPG);
  
  	printf(version);
  	identifycpu();
Index: sys/arch/i386/i386/pmap.c
===================================================================
RCS file: /a/cvsroot/src/sys/arch/i386/i386/pmap.c,v
retrieving revision 1.34
diff -c -r1.34 pmap.c
*** pmap.c	1995/12/09 07:39:02	1.34
--- pmap.c	1996/01/05 03:09:16
***************
*** 180,186 ****
  pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
  
  #if BSDVM_COMPAT
! #include <sys/msgbuf.h>
  
  /*
   * All those kernel PT submaps that BSD is so fond of
--- 180,186 ----
  pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
  
  #if BSDVM_COMPAT
! extern caddr_t msgbufaddr;
  
  /*
   * All those kernel PT submaps that BSD is so fond of
***************
*** 214,220 ****
  	extern vm_offset_t reserve_dumppages(vm_offset_t);
  
  	/* XXX: allow for msgbuf */
! 	avail_end -= i386_round_page(sizeof(struct msgbuf));
  
  	virtual_avail = virtual_start;
  	virtual_end = VM_MAX_KERNEL_ADDRESS;
--- 214,220 ----
  	extern vm_offset_t reserve_dumppages(vm_offset_t);
  
  	/* XXX: allow for msgbuf */
! 	avail_end -= NBPG;
  
  	virtual_avail = virtual_start;
  	virtual_end = VM_MAX_KERNEL_ADDRESS;
***************
*** 258,267 ****
  	va = virtual_avail;
  	pte = pmap_pte(pmap_kernel(), va);
  
! 	SYSMAP(caddr_t		,CMAP1		,CADDR1	   ,1		)
! 	SYSMAP(caddr_t		,CMAP2		,CADDR2	   ,1		)
! 	SYSMAP(caddr_t		,XXX_mmap	,vmmap	   ,1		)
! 	SYSMAP(struct msgbuf *	,msgbufmap	,msgbufp   ,1		)
  	virtual_avail = va;
  #endif
  
--- 258,267 ----
  	va = virtual_avail;
  	pte = pmap_pte(pmap_kernel(), va);
  
! 	SYSMAP(caddr_t	,CMAP1		,CADDR1		,1	)
! 	SYSMAP(caddr_t	,CMAP2		,CADDR2		,1	)
! 	SYSMAP(caddr_t	,XXX_mmap	,vmmap		,1	)
! 	SYSMAP(caddr_t	,msgbufmap	,msgbufaddr	,1	)
  	virtual_avail = va;
  #endif
  
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /a/cvsroot/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.12
diff -c -r1.12 kern_sysctl.c
*** kern_sysctl.c	1995/10/07 06:28:27	1.12
--- kern_sysctl.c	1996/01/05 03:09:23
***************
*** 56,61 ****
--- 56,62 ----
  #include <sys/disklabel.h>
  #include <vm/vm.h>
  #include <sys/sysctl.h>
+ #include <sys/msgbuf.h>
  
  #include <sys/mount.h>
  #include <sys/syscallargs.h>
***************
*** 285,290 ****
--- 286,301 ----
  		return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
  	case KERN_RAWPARTITION:
  		return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
+ 	case KERN_MSGBUFSIZE:
+ 		/*
+ 		 * deal with cases where the message buffer has
+ 		 * become corrupted.
+ 		 */
+ 		if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
+ 			msgbufenabled = 0;
+ 			return (ENXIO);
+ 		}
+ 		return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
  	default:
  		return (EOPNOTSUPP);
  	}
Index: sys/kern/subr_log.c
===================================================================
RCS file: /a/cvsroot/src/sys/kern/subr_log.c,v
retrieving revision 1.8
diff -c -r1.8 subr_log.c
*** subr_log.c	1994/10/30 21:47:47	1.8
--- subr_log.c	1996/01/05 03:09:24
***************
*** 60,65 ****
--- 60,104 ----
  
  int	log_open;			/* also used in log() */
  
+ int	msgbufmapped;			/* is the message buffer mapped */
+ int	msgbufenabled;			/* is logging to the buffer enabled */
+ struct	kern_msgbuf *msgbufp;		/* the mapped buffer, itself. */
+ 
+ void
+ initmsgbuf(buf, bufsize)
+ 	caddr_t buf;
+ 	size_t bufsize;
+ {
+ 	register struct kern_msgbuf *mbp;
+ 	long new_bufs;
+ 
+ 	/* Sanity-check the given size. */
+ 	if (bufsize < sizeof(struct kern_msgbuf))
+ 		return;
+ 
+ 	mbp = msgbufp = (struct kern_msgbuf *)buf;
+ 
+ #define	offsetof(type, member)	((size_t)(&((type *)0)->member))
+ 	new_bufs = bufsize - offsetof(struct kern_msgbuf, msg_bufc);
+ #undef offsetof
+ 	if ((mbp->msg_magic != MSG_MAGIC) || (mbp->msg_bufs != new_bufs) ||
+ 	    (mbp->msg_bufr < 0) || (mbp->msg_bufr >= mbp->msg_bufs) ||
+ 	    (mbp->msg_bufx < 0) || (mbp->msg_bufx >= mbp->msg_bufs)) {
+ 		/*
+ 		 * If the buffer magic number is wrong, has changed
+ 		 * size (which shouldn't happen often), or is
+ 		 * internally inconsistent, initialize it.
+ 		 */
+ 
+ 		bzero(buf, bufsize);
+ 		mbp->msg_magic = MSG_MAGIC;
+ 		mbp->msg_bufs = new_bufs;
+ 	}
+ 
+ 	/* mark it as ready for use. */
+ 	msgbufmapped = msgbufenabled = 1;
+ }
+ 
  /*ARGSUSED*/
  int
  logopen(dev, flags, mode, p)
***************
*** 67,91 ****
  	int flags, mode;
  	struct proc *p;
  {
! 	register struct msgbuf *mbp = msgbufp;
  
  	if (log_open)
  		return (EBUSY);
  	log_open = 1;
  	logsoftc.sc_pgid = p->p_pid;		/* signal process only */
  	/*
! 	 * Potential race here with putchar() but since putchar should be
! 	 * called by autoconf, msg_magic should be initialized by the time
! 	 * we get here.
  	 */
  	if (mbp->msg_magic != MSG_MAGIC) {
! 		register int i;
! 
! 		mbp->msg_magic = MSG_MAGIC;
! 		mbp->msg_bufx = mbp->msg_bufr = 0;
! 		for (i=0; i < MSG_BSIZE; i++)
! 			mbp->msg_bufc[i] = 0;
  	}
  	return (0);
  }
  
--- 106,129 ----
  	int flags, mode;
  	struct proc *p;
  {
! 	register struct kern_msgbuf *mbp = msgbufp;
  
  	if (log_open)
  		return (EBUSY);
  	log_open = 1;
  	logsoftc.sc_pgid = p->p_pid;		/* signal process only */
+ 
  	/*
! 	 * The message buffer is initialized during system configuration.
! 	 * If it's been clobbered, note that and return an error.  (This
! 	 * allows a user to potentially read the buffer via /dev/kmem,
! 	 * and try to figure out what clobbered it.
  	 */
  	if (mbp->msg_magic != MSG_MAGIC) {
! 		msgbufenabled = 0;
! 		return (ENXIO);
  	}
+ 
  	return (0);
  }
  
***************
*** 108,114 ****
  	struct uio *uio;
  	int flag;
  {
! 	register struct msgbuf *mbp = msgbufp;
  	register long l;
  	register int s;
  	int error = 0;
--- 146,152 ----
  	struct uio *uio;
  	int flag;
  {
! 	register struct kern_msgbuf *mbp = msgbufp;
  	register long l;
  	register int s;
  	int error = 0;
***************
*** 132,138 ****
  	while (uio->uio_resid > 0) {
  		l = mbp->msg_bufx - mbp->msg_bufr;
  		if (l < 0)
! 			l = MSG_BSIZE - mbp->msg_bufr;
  		l = min(l, uio->uio_resid);
  		if (l == 0)
  			break;
--- 170,176 ----
  	while (uio->uio_resid > 0) {
  		l = mbp->msg_bufx - mbp->msg_bufr;
  		if (l < 0)
! 			l = mbp->msg_bufs - mbp->msg_bufr;
  		l = min(l, uio->uio_resid);
  		if (l == 0)
  			break;
***************
*** 141,147 ****
  		if (error)
  			break;
  		mbp->msg_bufr += l;
! 		if (mbp->msg_bufr < 0 || mbp->msg_bufr >= MSG_BSIZE)
  			mbp->msg_bufr = 0;
  	}
  	return (error);
--- 179,185 ----
  		if (error)
  			break;
  		mbp->msg_bufr += l;
! 		if (mbp->msg_bufr < 0 || mbp->msg_bufr >= mbp->msg_bufs)
  			mbp->msg_bufr = 0;
  	}
  	return (error);
***************
*** 209,215 ****
  		l = msgbufp->msg_bufx - msgbufp->msg_bufr;
  		splx(s);
  		if (l < 0)
! 			l += MSG_BSIZE;
  		*(int *)data = l;
  		break;
  
--- 247,253 ----
  		l = msgbufp->msg_bufx - msgbufp->msg_bufr;
  		splx(s);
  		if (l < 0)
! 			l += msgbufp->msg_bufs;
  		*(int *)data = l;
  		break;
  
Index: sys/kern/subr_prf.c
===================================================================
RCS file: /a/cvsroot/src/sys/kern/subr_prf.c,v
retrieving revision 1.19
diff -c -r1.19 subr_prf.c
*** subr_prf.c	1995/06/16 10:52:17	1.19
--- subr_prf.c	1996/01/05 03:09:24
***************
*** 488,495 ****
  	int flags;
  	struct tty *tp;
  {
! 	extern int msgbufmapped;
! 	register struct msgbuf *mbp;
  
  	if (panicstr)
  		constty = NULL;
--- 488,494 ----
  	int flags;
  	struct tty *tp;
  {
! 	register struct kern_msgbuf *mbp;
  
  	if (panicstr)
  		constty = NULL;
***************
*** 501,515 ****
  	    (flags & TOCONS) && tp == constty)
  		constty = NULL;
  	if ((flags & TOLOG) &&
! 	    c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
  		mbp = msgbufp;
  		if (mbp->msg_magic != MSG_MAGIC) {
! 			bzero((caddr_t)mbp, sizeof(*mbp));
! 			mbp->msg_magic = MSG_MAGIC;
  		}
- 		mbp->msg_bufc[mbp->msg_bufx++] = c;
- 		if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
- 			mbp->msg_bufx = 0;
  	}
  	if ((flags & TOCONS) && constty == NULL && c != '\0')
  		(*v_putc)(c);
--- 500,523 ----
  	    (flags & TOCONS) && tp == constty)
  		constty = NULL;
  	if ((flags & TOLOG) &&
! 	    c != '\0' && c != '\r' && c != 0177 && msgbufenabled) {
  		mbp = msgbufp;
  		if (mbp->msg_magic != MSG_MAGIC) {
! 			/*
! 			 * Arguably should panic or somehow notify the
! 			 * user...  but how?  Panic may be too drastic,
! 			 * and would obliterate the message being kicked
! 			 * out (maybe a panic itself), and printf
! 			 * would invoke us recursively.  Silently punt
! 			 * for now.  If syslog is running, it should
! 			 * notice.
! 			 */
! 			msgbufenabled = 0;
! 		} else {
! 			mbp->msg_bufc[mbp->msg_bufx++] = c;
! 			if (mbp->msg_bufx < 0 || mbp->msg_bufx >= mbp->msg_bufs)
! 				mbp->msg_bufx = 0;
  		}
  	}
  	if ((flags & TOCONS) && constty == NULL && c != '\0')
  		(*v_putc)(c);
Index: sys/miscfs/kernfs/kernfs_vnops.c
===================================================================
RCS file: /a/cvsroot/src/sys/miscfs/kernfs/kernfs_vnops.c,v
retrieving revision 1.39
diff -c -r1.39 kernfs_vnops.c
*** kernfs_vnops.c	1995/10/09 14:25:02	1.39
--- kernfs_vnops.c	1996/01/05 03:09:31
***************
*** 140,154 ****
  	}
  
  	case KTT_MSGBUF: {
- 		extern struct msgbuf *msgbufp;
  		long n;
  
! 		if (off >= MSG_BSIZE)
  			return (0);
  		n = msgbufp->msg_bufx + off;
! 		if (n >= MSG_BSIZE)
! 			n -= MSG_BSIZE;
! 		len = min(MSG_BSIZE - n, MSG_BSIZE - off);
  		*bufp = msgbufp->msg_bufc + n;
  		return (len);
  	}
--- 140,171 ----
  	}
  
  	case KTT_MSGBUF: {
  		long n;
  
! 		/*
! 		 * deal with cases where the message buffer has
! 		 * become corrupted.
! 		 */
! 		if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
! 			msgbufenabled = 0;
! 			return (ENXIO);
! 		}
! 
! 		/*
! 		 * Note that reads of /kern/msgbuf won't necessarily yeild
! 		 * consistent results, if the message buffer is modified
! 		 * while the read is in progress.  The worst that can happen
! 		 * is that incorrect data will be read.  There's no way
! 		 * that this can crash the system unless the values in the
! 		 * message buffer header are corrupted, but that'll cause
! 		 * the system to die anyway.
! 		 */
! 		if (off >= msgbufp->msg_bufs)
  			return (0);
  		n = msgbufp->msg_bufx + off;
! 		if (n >= msgbufp->msg_bufs)
! 			n -= msgbufp->msg_bufs;
! 		len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
  		*bufp = msgbufp->msg_bufc + n;
  		return (len);
  	}
Index: sys/sys/msgbuf.h
===================================================================
RCS file: /a/cvsroot/src/sys/sys/msgbuf.h,v
retrieving revision 1.8
diff -c -r1.8 msgbuf.h
*** msgbuf.h	1995/03/26 20:24:27	1.8
--- msgbuf.h	1996/01/05 03:09:41
***************
*** 35,48 ****
   *	@(#)msgbuf.h	8.1 (Berkeley) 6/2/93
   */
  
! #define	MSG_BSIZE	(4096 - 3 * sizeof(long))
! struct	msgbuf {
  #define	MSG_MAGIC	0x063061
  	long	msg_magic;
  	long	msg_bufx;		/* write pointer */
  	long	msg_bufr;		/* read pointer */
! 	char	msg_bufc[MSG_BSIZE];	/* buffer */
  };
  #ifdef _KERNEL
! struct	msgbuf *msgbufp;
  #endif
--- 35,53 ----
   *	@(#)msgbuf.h	8.1 (Berkeley) 6/2/93
   */
  
! struct	kern_msgbuf {
  #define	MSG_MAGIC	0x063061
  	long	msg_magic;
  	long	msg_bufx;		/* write pointer */
  	long	msg_bufr;		/* read pointer */
! 	long	msg_bufs;		/* real msg_bufc size (bytes) */
! 	char	msg_bufc[1];		/* buffer */
  };
+ 
  #ifdef _KERNEL
! extern int	msgbufmapped;		/* is the message buffer mapped */
! extern int	msgbufenabled;		/* is logging to the buffer enabled */
! extern struct	kern_msgbuf *msgbufp;	/* the mapped buffer, itself. */
! 
! void	initmsgbuf __P((caddr_t buf, size_t bufsize));
  #endif
Index: sys/sys/sysctl.h
===================================================================
RCS file: /a/cvsroot/src/sys/sys/sysctl.h,v
retrieving revision 1.9
diff -c -r1.9 sysctl.h
*** sysctl.h	1995/08/04 18:36:08	1.9
--- sysctl.h	1996/01/05 03:09:42
***************
*** 132,138 ****
  #define	KERN_DOMAINNAME		22	/* string: (YP) domainname */
  #define	KERN_MAXPARTITIONS	23	/* int: number of partitions/disk */
  #define KERN_RAWPARTITION	24	/* int: raw partition number */
! #define	KERN_MAXID		25	/* number of valid kern ids */
  
  #define CTL_KERN_NAMES { \
  	{ 0, 0 }, \
--- 132,139 ----
  #define	KERN_DOMAINNAME		22	/* string: (YP) domainname */
  #define	KERN_MAXPARTITIONS	23	/* int: number of partitions/disk */
  #define KERN_RAWPARTITION	24	/* int: raw partition number */
! #define KERN_MSGBUFSIZE		25	/* int: max # of chars in msg buffer */
! #define	KERN_MAXID		26	/* number of valid kern ids */
  
  #define CTL_KERN_NAMES { \
  	{ 0, 0 }, \
***************
*** 160,165 ****
--- 161,167 ----
  	{ "domainname", CTLTYPE_STRING }, \
  	{ "maxpartitions", CTLTYPE_INT }, \
  	{ "rawpartition", CTLTYPE_INT }, \
+ 	{ "msgbufsize", CTLTYPE_INT }, \
  }
  
  /* 
Index: usr.sbin/sysctl/sysctl.8
===================================================================
RCS file: /a/cvsroot/src/usr.sbin/sysctl/sysctl.8,v
retrieving revision 1.4
diff -c -r1.4 sysctl.8
*** sysctl.8	1995/09/30 07:12:49	1.4
--- sysctl.8	1996/01/05 03:09:50
***************
*** 110,115 ****
--- 110,116 ----
  .It kern.maxproc	integer	yes
  .It kern.maxfiles	integer	yes
  .It kern.maxpartitions	integer	no
+ .It kern.msgbufsize	integer	no
  .It kern.rawpartition	integer	no
  .It kern.argmax	integer	no
  .It kern.securelevel	integer	raise only
Index: usr.sbin/syslogd/syslogd.c
===================================================================
RCS file: /a/cvsroot/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.5
diff -c -r1.5 syslogd.c
*** syslogd.c	1996/01/02 17:48:41	1.5
--- syslogd.c	1996/01/05 03:09:55
***************
*** 81,86 ****
--- 81,87 ----
  #include <sys/un.h>
  #include <sys/time.h>
  #include <sys/resource.h>
+ #include <sys/sysctl.h>
  
  #include <netinet/in.h>
  #include <netdb.h>
***************
*** 194,199 ****
--- 195,201 ----
  void	die __P((int));
  void	domark __P((int));
  void	fprintlog __P((struct filed *, int, char *));
+ int	getmsgbufsize __P((void));
  void	init __P((int));
  void	logerror __P((char *));
  void	logmsg __P((int, char *, char *, int));
***************
*** 209,219 ****
  	int argc;
  	char *argv[];
  {
! 	int ch, funix, i, inetm, fklog, klogm, len;
  	struct sockaddr_un sunx, fromunix;
  	struct sockaddr_in sin, frominet;
  	FILE *fp;
! 	char *p, line[MSG_BSIZE + 1];
  
  	while ((ch = getopt(argc, argv, "df:m:p:")) != EOF)
  		switch(ch) {
--- 211,221 ----
  	int argc;
  	char *argv[];
  {
! 	int ch, funix, i, inetm, fklog, klogm, len, linesize;
  	struct sockaddr_un sunx, fromunix;
  	struct sockaddr_in sin, frominet;
  	FILE *fp;
! 	char *p, *line;
  
  	while ((ch = getopt(argc, argv, "df:m:p:")) != EOF)
  		switch(ch) {
***************
*** 249,254 ****
--- 251,265 ----
  		LocalDomain = p;
  	} else
  		LocalDomain = "";
+ 	linesize = getmsgbufsize();
+ 	if (linesize < MAXLINE)
+ 		linesize = MAXLINE;
+ 	linesize++;
+ 	line = malloc(linesize);
+ 	if (line == NULL) {
+ 		logerror("couldn't allocate line buffer");
+ 		die(0);
+ 	}
  	(void)signal(SIGTERM, die);
  	(void)signal(SIGINT, Debug ? die : SIG_IGN);
  	(void)signal(SIGQUIT, Debug ? die : SIG_IGN);
***************
*** 329,335 ****
  		}
  		dprintf("got a message (%d, %#x)\n", nfds, readfds);
  		if (readfds & klogm) {
! 			i = read(fklog, line, sizeof(line) - 1);
  			if (i > 0) {
  				line[i] = '\0';
  				printsys(line);
--- 340,346 ----
  		}
  		dprintf("got a message (%d, %#x)\n", nfds, readfds);
  		if (readfds & klogm) {
! 			i = read(fklog, line, linesize - 1);
  			if (i > 0) {
  				line[i] = '\0';
  				printsys(line);
***************
*** 1132,1135 ****
--- 1143,1165 ----
  			return (c->c_val);
  
  	return (-1);
+ }
+ 
+ /*
+  * Retrieve the size of the kernel message buffer, via sysctl.
+  */
+ int
+ getmsgbufsize()
+ {
+ 	int msgbufsize, mib[2];
+ 	size_t size;
+ 
+ 	mib[0] = CTL_KERN;
+ 	mib[1] = KERN_MSGBUFSIZE;
+ 	size = sizeof msgbufsize;
+ 	if (sysctl(mib, 2, &msgbufsize, &size, NULL, 0) == -1) {
+ 		dprintf("couldn't get kern.msgbufsize\n");
+ 		return (0);
+ 	}
+ 	return (msgbufsize);
  }
Index: sbin/dmesg/dmesg.c
===================================================================
RCS file: /a/cvsroot/src/sbin/dmesg/dmesg.c,v
retrieving revision 1.8
diff -c -r1.8 dmesg.c
*** dmesg.c	1995/03/18 14:54:49	1.8
--- dmesg.c	1996/01/05 03:21:25
***************
*** 79,86 ****
  {
  	register int ch, newl, skip;
  	register char *p, *ep;
! 	struct msgbuf *bufp, cur;
! 	char *memf, *nlistf;
  	kvm_t *kd;
  	char buf[5];
  
--- 79,86 ----
  {
  	register int ch, newl, skip;
  	register char *p, *ep;
! 	struct kern_msgbuf *bufp, cur;
! 	char *memf, *nlistf, *bufdata;
  	kvm_t *kd;
  	char buf[5];
  
***************
*** 107,113 ****
  	if (memf != NULL || nlistf != NULL)
  		setgid(getgid());
  
! 	/* Read in kernel message buffer, do sanity checks. */
  	if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg")) == NULL)
  		exit (1);
  	if (kvm_nlist(kd, nl) == -1)
--- 107,113 ----
  	if (memf != NULL || nlistf != NULL)
  		setgid(getgid());
  
! 	/* Read in message buffer header and data, and do sanity checks. */
  	if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg")) == NULL)
  		exit (1);
  	if (kvm_nlist(kd, nl) == -1)
***************
*** 116,136 ****
  		errx(1, "%s: msgbufp not found", nlistf ? nlistf : "namelist");
  	if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
  		errx(1, "kvm_read: %s", kvm_geterr(kd));
- 	kvm_close(kd);
  	if (cur.msg_magic != MSG_MAGIC)
  		errx(1, "magic number incorrect");
! 	if (cur.msg_bufx >= MSG_BSIZE)
  		cur.msg_bufx = 0;
  
  	/*
  	 * The message buffer is circular; start at the read pointer, and
  	 * go to the write pointer - 1.
  	 */
! 	p = cur.msg_bufc + cur.msg_bufx;
! 	ep = cur.msg_bufc + cur.msg_bufx - 1;
  	for (newl = skip = 0; p != ep; ++p) {
! 		if (p == cur.msg_bufc + MSG_BSIZE)
! 			p = cur.msg_bufc;
  		ch = *p;
  		/* Skip "\n<.*>" syslog sequences. */
  		if (skip) {
--- 116,142 ----
  		errx(1, "%s: msgbufp not found", nlistf ? nlistf : "namelist");
  	if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
  		errx(1, "kvm_read: %s", kvm_geterr(kd));
  	if (cur.msg_magic != MSG_MAGIC)
  		errx(1, "magic number incorrect");
! 	bufdata = malloc(cur.msg_bufs);
! 	if (bufdata == NULL)
! 		errx(1, "couldn't allocate space for buffer data");
! 	if (kvm_read(kd, (long)&bufp->msg_bufc, bufdata,
! 	    cur.msg_bufs) != cur.msg_bufs)
! 		errx(1, "kvm_read: %s", kvm_geterr(kd));
! 	kvm_close(kd);
! 	if (cur.msg_bufx >= cur.msg_bufs)
  		cur.msg_bufx = 0;
  
  	/*
  	 * The message buffer is circular; start at the read pointer, and
  	 * go to the write pointer - 1.
  	 */
! 	p = bufdata + cur.msg_bufx;
! 	ep = bufdata + cur.msg_bufx - 1;
  	for (newl = skip = 0; p != ep; ++p) {
! 		if (p == bufdata + cur.msg_bufs)
! 			p = bufdata;
  		ch = *p;
  		/* Skip "\n<.*>" syslog sequences. */
  		if (skip) {
>Audit-Trail:
>Unformatted: