summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2014-12-09 00:47:02 +0000
committerdelphij <delphij@FreeBSD.org>2014-12-09 00:47:02 +0000
commit04dbe28cc60491c8073ccf83e8123b9fb2ed69ec (patch)
treedf4502f8b5dec9e9d21cdde284e71865a5ea7599
parent0fb6d9ca37798e3eae066f99155d1afc2a28b26d (diff)
downloadFreeBSD-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.c37
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,
OpenPOWER on IntegriCloud