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
MFC after:	2 weeks
Differential Revision: https://reviews.freebsd.org/D1227
This commit is contained in:
Xin LI 2014-11-25 20:59:22 +00:00
parent 92fc4f553a
commit 52e05d9a24

View File

@ -261,26 +261,45 @@ vsyslog(int pri, const char *fmt, va_list ap)
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_list ap)
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,