diff options
author | delphij <delphij@FreeBSD.org> | 2014-12-09 00:47:02 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2014-12-09 00:47:02 +0000 |
commit | 04dbe28cc60491c8073ccf83e8123b9fb2ed69ec (patch) | |
tree | df4502f8b5dec9e9d21cdde284e71865a5ea7599 | |
parent | 0fb6d9ca37798e3eae066f99155d1afc2a28b26d (diff) | |
download | FreeBSD-src-04dbe28cc60491c8073ccf83e8123b9fb2ed69ec.zip FreeBSD-src-04dbe28cc60491c8073ccf83e8123b9fb2ed69ec.tar.gz |
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
-rw-r--r-- | lib/libc/gen/syslog.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c index 6357761..cbe32a5 100644 --- a/lib/libc/gen/syslog.c +++ b/lib/libc/gen/syslog.c @@ -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, |