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:
parent
92fc4f553a
commit
52e05d9a24
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user