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
This commit is contained in:
delphij 2014-12-09 00:47:02 +00:00
parent 0fb6d9ca37
commit 04dbe28cc6

View File

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