Skip to content

Commit

Permalink
MFC r275071:
Browse files Browse the repository at this point in the history
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
  • Loading branch information
delphij committed Dec 9, 2014
1 parent 47b2804 commit 834776a
Showing 1 changed file with 28 additions and 9 deletions.
37 changes: 28 additions & 9 deletions lib/libc/gen/syslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,34 +261,53 @@ 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);
if (send(LogFile, tbuf, cnt, 0) >= 0) {
THREAD_UNLOCK();
return;
}
} while (errno == ENOBUFS);
}
} else {
THREAD_UNLOCK();
return;
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 834776a

Please sign in to comment.