From ilepore@damnhippie.dyndns.org  Sat Sep  3 19:00:51 2011
Return-Path: <ilepore@damnhippie.dyndns.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id AFBC4106566C
	for <freebsd-gnats-submit@freebsd.org>; Sat,  3 Sep 2011 19:00:51 +0000 (UTC)
	(envelope-from ilepore@damnhippie.dyndns.org)
Received: from qmta03.emeryville.ca.mail.comcast.net (qmta03.emeryville.ca.mail.comcast.net [76.96.30.32])
	by mx1.freebsd.org (Postfix) with ESMTP id 964718FC0C
	for <freebsd-gnats-submit@freebsd.org>; Sat,  3 Sep 2011 19:00:51 +0000 (UTC)
Received: from omta18.emeryville.ca.mail.comcast.net ([76.96.30.74])
	by qmta03.emeryville.ca.mail.comcast.net with comcast
	id UJzY1h0021bwxycA3K0mek; Sat, 03 Sep 2011 19:00:46 +0000
Received: from damnhippie.dyndns.org ([24.8.232.202])
	by omta18.emeryville.ca.mail.comcast.net with comcast
	id UK2C1h00M4NgCEG8eK2D90; Sat, 03 Sep 2011 19:02:13 +0000
Received: from revolution.hippie.lan (revolution.hippie.lan [172.22.42.240])
	by damnhippie.dyndns.org (8.14.3/8.14.3) with ESMTP id p83J0nJP034074
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 3 Sep 2011 13:00:49 -0600 (MDT)
	(envelope-from ilepore@damnhippie.dyndns.org)
Received: (from ilepore@localhost)
	by revolution.hippie.lan (8.14.4/8.14.4/Submit) id p83J0n36099006;
	Sat, 3 Sep 2011 13:00:49 -0600 (MDT)
	(envelope-from ilepore)
Message-Id: <201109031900.p83J0n36099006@revolution.hippie.lan>
Date: Sat, 3 Sep 2011 13:00:49 -0600 (MDT)
From: Ian Lepore <freebsd@damnhippie.dyndns.org>
Reply-To: Ian Lepore <freebsd@damnhippie.dyndns.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] syslogd receiver buffer sizes set incorrectly
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         160433
>Category:       bin
>Synopsis:       [patch] syslogd(8) receiver buffer sizes set incorrectly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    melifaro
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Sep 03 19:10:07 UTC 2011
>Closed-Date:    Wed Feb 12 16:24:45 CST 2014
>Last-Modified:  Wed Feb 12 16:24:45 CST 2014
>Originator:     Ian Lepore <freebsd@damnhippie.dyndns.org>
>Release:        FreeBSD 8.2-RC3 arm
>Organization:
none
>Environment:
FreeBSD dvb 8.2-RC3 FreeBSD 8.2-RC3 #49: Tue Feb 15 22:52:14 UTC 2011     root@revolution.hippie.lan:/usr/obj/arm/usr/src/sys/DVB  arm

>Description:
This change fixes 3 problems in syslogd related to sizing receive buffers.

 - A call was misplaced at the wrong level of nested if blocks, so that the
   buffers for unix domain sockets (/dev/log, /dev/klog) were never increased
   at all; they remained at a way-too-small default size of 4096.

- The function that was supposed to double the size of the buffer sometimes 
  did nothing, and sometimes installed a wildly-wrong buffer size (either too 
  large or too small) due to an unitialized arglen variable passed to 
  getsockopt().  Most often it doubled the UDP buffers from 40k to 80k because 
  accidentally there would be harmless stack garbage in the unitialized 
  variables.  

- The whole concept of blindly doubling a socket's buffer size without 
  knowing what size it started at seems like a design flaw.  If the 
  double_rbuf() function had worked at all (I.E., if the other two bugs didn't 
  exist) this would lead to UDP sockets having an 80k buffer while unix dgram 
  sockets get an 8k buffer.  There's nothing about the problem being solved 
  that requires larger buffers for UDP than for unix dgram sockets -- the 
  buffering requirements are the same regardless of socket type.  

This change renames the double_rbuf() function to increase_rbuf() and 
increases the buffer size on all types of sockets to 80k.  80k was chosen 
only because it appears to be the size the original change was shooting for, 
and it certainly seems to be reasonably large (I might have picked 64k in 
the absence of any historical guidance).  

This change also fixes a problem where syslogd is too quick to close sockets
on errors.  Add a couple more error codes to ignore from sendto(), so that 
transient errors (such as would occur when restarting a network interface,
for example) get recovered.


>How-To-Repeat:
Log lots of messages from an app running on a heavily-loaded underpowered
system such as a 200mhz ARM; without the larger buffers for the unix-domain
sockets many messages get dropped in such an environment.

>Fix:
This problem was discovered in the 8.2 environment, but this diff/patch
is to -current.


--- diff.tmp begins here ---
Index: syslogd.c
===================================================================
RCS file: /local/base/FreeBSD-CVS/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.169
diff -u -p -r1.169 syslogd.c
--- syslogd.c	14 Jul 2011 07:33:53 -0000	1.169
+++ syslogd.c	3 Sep 2011 18:41:55 -0000
@@ -74,6 +74,7 @@ __FBSDID("$FreeBSD: src/usr.sbin/syslogd
 #define	DEFSPRI		(LOG_KERN|LOG_CRIT)
 #define	TIMERINTVL	30		/* interval for checking flush, mark */
 #define	TTYMSGTIME	1		/* timeout passed to ttymsg */
+#define	RCVBUF_MINSIZE	(80 * 1024)	/* minimum size of dgram rcv buffer */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
@@ -336,7 +337,7 @@ static void	unmapped(struct sockaddr *);
 static void	wallmsg(struct filed *, struct iovec *, const int iovlen);
 static int	waitdaemon(int, int, int);
 static void	timedout(int);
-static void	double_rbuf(int);
+static void	increase_rcvbuf(int);
 
 int
 main(int argc, char *argv[])
@@ -547,8 +548,8 @@ main(int argc, char *argv[])
 				STAILQ_REMOVE(&funixes, fx, funix, next);
 				continue;
 			}
-			double_rbuf(fx->s);
 		}
+		increase_rcvbuf(fx->s);
 	}
 	if (SecureMode <= 1)
 		finet = socksetup(family, bindhostname);
@@ -1241,8 +1242,10 @@ fprintlog(struct filed *f, int flags, co
 				switch (errno) {
 				case ENOBUFS:
 				case ENETDOWN:
+				case ENETUNREACH:
 				case EHOSTUNREACH:
 				case EHOSTDOWN:
+				case EADDRNOTAVAIL:
 					break;
 				/* case EBADF: */
 				/* case EACCES: */
@@ -1253,7 +1256,7 @@ fprintlog(struct filed *f, int flags, co
 				/* case ENOBUFS: */
 				/* case ECONNREFUSED: */
 				default:
-					dprintf("removing entry\n");
+					dprintf("removing entry: errno=%d\n", e);
 					f->f_type = F_UNUSED;
 					break;
 				}
@@ -2697,6 +2700,9 @@ socksetup(int af, char *bindhostname)
 		 * If the system administrator choose not to obey
 		 * this, we can skip the bind() step so that the
 		 * system will choose a port for us.
+		 *
+		 * In SecureMode we will shutdown() the receive side of
+		 * the socket, so no need for a bigger receiver buffer.
 		 */
 		if (!NoBind) {
 			if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
@@ -2704,9 +2710,8 @@ socksetup(int af, char *bindhostname)
 				logerror("bind");
 				continue;
 			}
-
 			if (!SecureMode)
-				double_rbuf(*s);
+				increase_rcvbuf(*s);
 		}
 
 		(*socks)++;
@@ -2727,12 +2732,15 @@ socksetup(int af, char *bindhostname)
 }
 
 static void
-double_rbuf(int fd)
+increase_rcvbuf(int fd)
 {
-	socklen_t slen, len;
+	socklen_t len;
+	socklen_t slen = sizeof(len);
 
 	if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, &slen) == 0) {
-		len *= 2;
-		setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, slen);
+		if (len < RCVBUF_MINSIZE) {
+			len = RCVBUF_MINSIZE;
+			setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
+		}
 	}
 }
--- diff.tmp ends here ---

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->melifaro 
Responsible-Changed-By: melifaro 
Responsible-Changed-When: Fri Jul 13 22:40:00 UTC 2012 
Responsible-Changed-Why:  
Take 

http://www.freebsd.org/cgi/query-pr.cgi?pr=160433 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/160433: commit references a PR
Date: Wed, 13 Nov 2013 01:01:23 +0000 (UTC)

 Author: ian
 Date: Wed Nov 13 01:01:15 2013
 New Revision: 258076
 URL: http://svnweb.freebsd.org/changeset/base/258076
 
 Log:
   This fixes 3 problems in syslogd related to sizing receive buffers...
   
   - A call was misplaced at the wrong level of nested if blocks, so that
     the buffers for unix domain sockets (/dev/log, /dev/klog) were never
     increased at all; they remained at a way-too-small default size of 4096.
   
   - The function that was supposed to double the size of the buffer
     sometimes did nothing, and sometimes installed a wildly-wrong buffer
     size (either too large or too small) due to an unitialized 'slen'
     variable passed to getsockopt().  Most often it doubled the UDP buffers
     from 40k to 80k because accidentally there would be harmless stack
     garbage in the unitialized variables.
   
   - The whole concept of blindly doubling a socket's buffer size without
     knowing what size it started at is a design flaw that has to be called a
     bug.  If the double_rbuf() function had worked at all (I.E., if the
     other two bugs didn't exist) this would lead to UDP sockets having an
     80k buffer while unix dgram sockets get an 8k buffer.  There's nothing
     about the problem being solved that requires larger buffers for UDP than
     for unix dgram sockets -- the buffering requirements are the same
     regardless of socket type.
   
   This change renames the double_rbuf() function to increase_rbuf() and
   increases the buffer size on all types of sockets to 80k.  80k was
   chosen only because it appears to be the size the original change was
   shooting for, and it certainly seems to be reasonably large (I might
   have picked 64k in the absence of any historical guidance).
   
   PR:		160433
   Submitted by:	me, in 2011.
 
 Modified:
   head/usr.sbin/syslogd/syslogd.c
 
 Modified: head/usr.sbin/syslogd/syslogd.c
 ==============================================================================
 --- head/usr.sbin/syslogd/syslogd.c	Tue Nov 12 22:51:03 2013	(r258075)
 +++ head/usr.sbin/syslogd/syslogd.c	Wed Nov 13 01:01:15 2013	(r258076)
 @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$");
  #define	DEFSPRI		(LOG_KERN|LOG_CRIT)
  #define	TIMERINTVL	30		/* interval for checking flush, mark */
  #define	TTYMSGTIME	1		/* timeout passed to ttymsg */
 +#define	RCVBUF_MINSIZE	(80 * 1024)	/* minimum size of dgram rcv buffer */
  
  #include <sys/param.h>
  #include <sys/ioctl.h>
 @@ -336,7 +337,7 @@ static void	unmapped(struct sockaddr *);
  static void	wallmsg(struct filed *, struct iovec *, const int iovlen);
  static int	waitdaemon(int, int, int);
  static void	timedout(int);
 -static void	double_rbuf(int);
 +static void	increase_rcvbuf(int);
  
  int
  main(int argc, char *argv[])
 @@ -547,8 +548,8 @@ main(int argc, char *argv[])
  				STAILQ_REMOVE(&funixes, fx, funix, next);
  				continue;
  			}
 -			double_rbuf(fx->s);
  		}
 +		increase_rcvbuf(fx->s);
  	}
  	if (SecureMode <= 1)
  		finet = socksetup(family, bindhostname);
 @@ -2720,7 +2721,7 @@ socksetup(int af, char *bindhostname)
  			}
  
  			if (!SecureMode)
 -				double_rbuf(*s);
 +				increase_rcvbuf(*s);
  		}
  
  		(*socks)++;
 @@ -2741,12 +2742,16 @@ socksetup(int af, char *bindhostname)
  }
  
  static void
 -double_rbuf(int fd)
 +increase_rcvbuf(int fd)
  {
 -	socklen_t slen, len;
 +	socklen_t len, slen;
 +
 +	slen = sizeof(len);
  
  	if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, &slen) == 0) {
 -		len *= 2;
 -		setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, slen);
 +		if (len < RCVBUF_MINSIZE) {
 +			len = RCVBUF_MINSIZE;
 +			setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
 +		}
  	}
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: bdrewery 
State-Changed-When: Wed Feb 12 16:24:44 CST 2014 
State-Changed-Why:  
already committed 

http://www.freebsd.org/cgi/query-pr.cgi?pr=160433 
>Unformatted:
