aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc/gen/syslog.c54
-rw-r--r--sys/sys/syslog.h1
-rw-r--r--usr.sbin/syslogd/syslogd.89
-rw-r--r--usr.sbin/syslogd/syslogd.c10
4 files changed, 56 insertions, 18 deletions
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c
index 5d3a90f135c8..93c41468a77f 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 */
diff --git a/sys/sys/syslog.h b/sys/sys/syslog.h
index bc18d6961c6e..8b216d4da37e 100644
--- a/sys/sys/syslog.h
+++ b/sys/sys/syslog.h
@@ -34,6 +34,7 @@
#define _SYS_SYSLOG_H_
#define _PATH_LOG "/var/run/log"
+#define _PATH_LOG_PRIV "/var/run/logpriv"
#define _PATH_OLDLOG "/dev/log" /* backward compatibility */
/*
diff --git a/usr.sbin/syslogd/syslogd.8 b/usr.sbin/syslogd/syslogd.8
index 2e276bd74dc6..5514fd5103f5 100644
--- a/usr.sbin/syslogd/syslogd.8
+++ b/usr.sbin/syslogd/syslogd.8
@@ -250,8 +250,10 @@ The
.Nm
utility reads messages from the
.Ux
-domain socket
-.Pa /var/run/log ,
+domain sockets
+.Pa /var/run/log
+and
+.Pa /var/run/logpriv ,
from an Internet domain socket specified in
.Pa /etc/services ,
and from the special device
@@ -293,6 +295,9 @@ default process ID file
name of the
.Ux
domain datagram log socket
+.It Pa /var/run/logpriv
+.Ux
+socket for priveleged applications
.It Pa /dev/klog
kernel log device
.El
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 38480eedfbac..ed266d45e017 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -129,6 +129,8 @@ const char ctty[] = _PATH_CONSOLE;
/*
* Unix sockets.
+ * We have two default sockets, one with 666 permissions,
+ * and one for priveleged programs
*/
struct funix {
int s;
@@ -136,11 +138,13 @@ struct funix {
mode_t mode;
STAILQ_ENTRY(funix) next;
};
-struct funix funix_default = { -1, _PATH_LOG, DEFFILEMODE,
+struct funix funix_secure = { -1, _PATH_LOG_PRIV, S_IRUSR | S_IWUSR,
{ NULL } };
+struct funix funix_default = { -1, _PATH_LOG, DEFFILEMODE,
+ { &funix_secure } };
STAILQ_HEAD(, funix) funixes = { &funix_default,
- &(funix_default.next.stqe_next) };
+ &(funix_secure.next.stqe_next) };
/*
* Flags to logmsg().
@@ -504,7 +508,7 @@ main(int argc, char *argv[])
"cannot create %s", fx->name);
logerror(line);
dprintf("cannot create %s (%d)\n", fx->name, errno);
- if (fx == &funix_default)
+ if (fx == &funix_default || fx == &funix_secure)
die(0);
else
STAILQ_REMOVE(&funixes, fx, funix, next);