diff options
-rw-r--r-- | lib/libc/gen/syslog.c | 54 | ||||
-rw-r--r-- | sys/sys/syslog.h | 1 | ||||
-rw-r--r-- | usr.sbin/syslogd/syslogd.8 | 9 | ||||
-rw-r--r-- | usr.sbin/syslogd/syslogd.c | 10 |
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); |