Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Dec 2014 00:47:47 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r275627 - stable/9/lib/libc/gen
Message-ID:  <201412090047.sB90llHM065423@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Tue Dec  9 00:47:46 2014
New Revision: 275627
URL: https://svnweb.freebsd.org/changeset/base/275627

Log:
  MFC r275071:
  
  Reinstitate send() after syslogd restarts.
  
  In r228193 the test of CONNPRIV have been moved to before the _usleep
  and send in vsyslog().  When syslogd restarts, this would prevent the
  message being logged after the disconnect/connect dance for
  scenario #1.
  
  PR:		194751
  Submitted by:	Peter Creath <pjcreath+freebsd gmail com>
  Reviewed By:	glebius

Modified:
  stable/9/lib/libc/gen/syslog.c
Directory Properties:
  stable/9/lib/libc/   (props changed)

Modified: stable/9/lib/libc/gen/syslog.c
==============================================================================
--- stable/9/lib/libc/gen/syslog.c	Tue Dec  9 00:47:02 2014	(r275626)
+++ stable/9/lib/libc/gen/syslog.c	Tue Dec  9 00:47:46 2014	(r275627)
@@ -261,26 +261,45 @@ vsyslog(int pri, const char *fmt, va_lis
 	connectlog();
 
 	/*
-	 * If the send() failed, there are two likely scenarios: 
+	 * If the send() fails, there are two likely scenarios: 
 	 *  1) syslogd was restarted
 	 *  2) /var/run/log is out of socket buffer space, which
 	 *     in most cases means local DoS.
-	 * We attempt to reconnect to /var/run/log[priv] to take care of
-	 * case #1 and keep send()ing data to cover case #2
-	 * to give syslogd a chance to empty its socket buffer.
+	 * If the error does not indicate a full buffer, we address
+	 * case #1 by attempting to reconnect to /var/run/log[priv]
+	 * and resending the message once.
 	 *
-	 * If we are working with a priveleged socket, then take
-	 * only one attempt, because we don't want to freeze a
+	 * If we are working with a privileged socket, the retry
+	 * attempts end there, because we don't want to freeze a
 	 * critical application like su(1) or sshd(8).
 	 *
+	 * Otherwise, we address case #2 by repeatedly retrying the
+	 * send() to give syslogd a chance to empty its socket buffer.
 	 */
 
 	if (send(LogFile, tbuf, cnt, 0) < 0) {
 		if (errno != ENOBUFS) {
+			/*
+			 * Scenario 1: syslogd was restarted
+			 * reconnect and resend once
+			 */
 			disconnectlog();
 			connectlog();
+			if (send(LogFile, tbuf, cnt, 0) >= 0) {
+				THREAD_UNLOCK();
+				return;
+			}
+			/*
+			 * if the resend failed, fall through to
+			 * possible scenario 2
+			 */
 		}
-		do {
+		while (errno == ENOBUFS) {
+			/*
+			 * Scenario 2: out of socket buffer space
+			 * possible DoS, fail fast on a privileged
+			 * socket
+			 */
 			if (status == CONNPRIV)
 				break;
 			_usleep(1);
@@ -288,7 +307,7 @@ vsyslog(int pri, const char *fmt, va_lis
 				THREAD_UNLOCK();
 				return;
 			}
-		} while (errno == ENOBUFS);
+		}
 	} else {
 		THREAD_UNLOCK();
 		return;
@@ -350,7 +369,7 @@ connectlog(void)
 		SyslogAddr.sun_family = AF_UNIX;
 
 		/*
-		 * First try priveleged socket. If no success,
+		 * First try privileged socket. If no success,
 		 * then try default socket.
 		 */
 		(void)strncpy(SyslogAddr.sun_path, _PATH_LOG_PRIV,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412090047.sB90llHM065423>