aboutsummaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2004-11-04 23:09:57 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2004-11-04 23:09:57 +0000
commit240d5a9b1ce76f04a7c7e15791557763b2f1fd7e (patch)
tree13d68b1840b739aaaa64351fb83f58c68c26472e /lib/libc
parent247444670ef3b61c7bdb3fbb34b88c4a26c71aba (diff)
Notes
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/syslog.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c
index 5d3a90f135c80..93c41468a77fb 100644
--- a/lib/libc/gen/syslog.c
+++ b/lib/libc/gen/syslog.c
@@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$");
#include "libc_private.h"
static int LogFile = -1; /* fd for log */
-static int connected; /* have done connect */
+static int status; /* connection status */
static int opened; /* have done openlog() */
static int LogStat = 0; /* status bits, set by openlog() */
static const char *LogTag = NULL; /* string to tag the entry with */
@@ -70,6 +70,12 @@ static int LogMask = 0xff; /* mask of priorities to be logged */
static void disconnectlog(void); /* disconnect from syslogd */
static void connectlog(void); /* (re)connect to syslogd */
+enum {
+ NOCONN = 0,
+ CONNDEF,
+ CONNPRIV,
+};
+
/*
* Format of the magic cookie passed through the stdio hook
*/
@@ -247,10 +253,16 @@ vsyslog(pri, fmt, ap)
/*
* If the send() failed, there are two likely scenarios:
* 1) syslogd was restarted
- * 2) /var/run/log is out of socket buffer space
+ * 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 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 we are working with a priveleged socket, then take
+ * only one attempt, because we don't want to freeze a
+ * critical application like su(1) or sshd(8).
+ *
*/
if (send(LogFile, tbuf, cnt, 0) < 0) {
@@ -262,6 +274,8 @@ vsyslog(pri, fmt, ap)
usleep(1);
if (send(LogFile, tbuf, cnt, 0) >= 0)
break;
+ if (status == CONNPRIV)
+ break;
} while (errno == ENOBUFS);
}
@@ -297,7 +311,7 @@ disconnectlog()
_close(LogFile);
LogFile = -1;
}
- connected = 0; /* retry connect */
+ status = NOCONN; /* retry connect */
}
static void
@@ -310,27 +324,41 @@ connectlog()
return;
(void)_fcntl(LogFile, F_SETFD, 1);
}
- if (LogFile != -1 && !connected) {
+ if (LogFile != -1 && status == NOCONN) {
SyslogAddr.sun_len = sizeof(SyslogAddr);
SyslogAddr.sun_family = AF_UNIX;
- (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
+
+ /*
+ * First try priveleged socket. If no success,
+ * then try default socket.
+ */
+ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG_PRIV,
sizeof SyslogAddr.sun_path);
- connected = _connect(LogFile, (struct sockaddr *)&SyslogAddr,
- sizeof(SyslogAddr)) != -1;
+ if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ sizeof(SyslogAddr)) != -1)
+ status = CONNPRIV;
+
+ if (status == NOCONN) {
+ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
+ sizeof SyslogAddr.sun_path);
+ if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ sizeof(SyslogAddr)) != -1)
+ status = CONNDEF;
+ }
- if (!connected) {
+ if (status == NOCONN) {
/*
* Try the old "/dev/log" path, for backward
* compatibility.
*/
(void)strncpy(SyslogAddr.sun_path, _PATH_OLDLOG,
sizeof SyslogAddr.sun_path);
- connected = _connect(LogFile,
- (struct sockaddr *)&SyslogAddr,
- sizeof(SyslogAddr)) != -1;
+ if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ sizeof(SyslogAddr)) != -1)
+ status = CONNDEF;
}
- if (!connected) {
+ if (status == NOCONN) {
(void)_close(LogFile);
LogFile = -1;
}
@@ -360,7 +388,7 @@ closelog()
(void)_close(LogFile);
LogFile = -1;
LogTag = NULL;
- connected = 0;
+ status = NOCONN;
}
/* setlogmask -- set the log mask level */