--- syslog.c 2014-11-01 15:47:23.000000000 -0400 +++ syslog.c 2014-11-01 21:03:57.000000000 -0400 @@ -262,24 +262,36 @@ /* - * 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; @@ -289,5 +301,5 @@ return; } - } while (errno == ENOBUFS); + }; } else { THREAD_UNLOCK();