From: | Xin LI <delphij@xxxxxxxxxxxxx> |
Date: | Sun, 4 Jul 2004 15:39:29 +0800 |
There was several changes since DragonFly's fork from RELENG_4: syslog.conf.5 (1.16.2.11 -> 1.16.2.13) syslogd.8 (1.22.2.16 -> 1.22.2.17) syslogd.c (1.59.2.26 -> 1.59.2.29) For detailed change comments please consult FreeBSD's cvs commitlog. Generally speaking, these changes improves security, cleans up the code, and give administrators the ablity to have some log files not to do sync after every changes, which is more friendly for busy mail servers, etc. I have attached a patchset to bring DragonFly's syslogd in sync with FreeBSD RELENG_4's. These changes are essentially the same with FreeBSD's changeset, as these code were not changed since the fork. Please consider to commit these changes before 1.0-RELEASE. Cheers, -- Xin LI <delphij frontfree net> http://www.delphij.net/ See complete headers for GPG key and other information.
Index: usr.sbin/syslogd/syslog.conf.5 =================================================================== RCS file: /home/dcvs/src/usr.sbin/syslogd/syslog.conf.5,v retrieving revision 1.2 diff -u -r1.2 syslog.conf.5 --- usr.sbin/syslogd/syslog.conf.5 17 Jun 2003 04:30:03 -0000 1.2 +++ usr.sbin/syslogd/syslog.conf.5 4 Jul 2004 07:24:52 -0000 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93 -.\" $FreeBSD: src/usr.sbin/syslogd/syslog.conf.5,v 1.16.2.11 2003/03/12 22:08:15 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/syslogd/syslog.conf.5,v 1.16.2.13 2004/06/29 10:07:35 dwmalone Exp $ .\" $DragonFly: src/usr.sbin/syslogd/syslog.conf.5,v 1.2 2003/06/17 04:30:03 dillon Exp $ .\" .Dd June 9, 1993 @@ -197,6 +197,15 @@ .Ql !-prog specification will match any message but the ones from that program. +Multiple programs may be listed, separated by commas: +.Ql !prog1,prog2 +matches messages from either program, while +.Ql !-prog1,prog2 +matches all messages but those from +.Ql prog1 +or +.Ql prog2 . +.Pp A .Em hostname specification of the form @@ -216,6 +225,9 @@ If the hostname is given as .Ql @ , the local hostname will be used. +As for program specifications, multiple comma-seprarated +values may be specified for hostname specifications. +.Pp A .Em program or @@ -307,6 +319,22 @@ .It A pathname (beginning with a leading slash). Selected messages are appended to the file. +.Pp +To ensure that kernel messages are written to disk promptly, +.Nm +calls +.Xr fsync 2 +after writing messages from the kernel. +Other messages are not synced explicitly. +You may prefix a pathname with the minus sign, +.Dq - , +to forego syncing the specified file after every kernel message. +Note that you might lose information if the system crashes +immediately following a write attempt. +Nevertheless, using the +.Dq - +option may improve performance, +especially if the kernel is logging many messages. .It A hostname (preceded by an at .Pq Dq @ @@ -411,6 +439,10 @@ # Log all writes to /dev/console to a separate file. console.* /var/log/console.log + +# Log ipfw messages without syncing after every message. +!ipfw +*.* -/var/log/ipfw .Ed .Sh IMPLEMENTATION NOTES The Index: usr.sbin/syslogd/syslogd.8 =================================================================== RCS file: /home/dcvs/src/usr.sbin/syslogd/syslogd.8,v retrieving revision 1.2 diff -u -r1.2 syslogd.8 --- usr.sbin/syslogd/syslogd.8 17 Jun 2003 04:30:03 -0000 1.2 +++ usr.sbin/syslogd/syslogd.8 4 Jul 2004 07:26:00 -0000 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)syslogd.8 8.1 (Berkeley) 6/6/93 -.\" $FreeBSD: src/usr.sbin/syslogd/syslogd.8,v 1.22.2.16 2003/03/12 22:08:15 trhodes Exp $ +.\" $FreeBSD: src/usr.sbin/syslogd/syslogd.8,v 1.22.2.17 2004/06/29 10:07:35 dwmalone Exp $ .\" $DragonFly: src/usr.sbin/syslogd/syslogd.8,v 1.2 2003/06/17 04:30:03 dillon Exp $ .\" .Dd November 24, 2001 @@ -260,7 +260,7 @@ .Sq Aq 5 . This priority code should map into the priorities defined in the include file -.Aq Pa sys/syslog.h . +.In sys/syslog.h . .Pp For security reasons, .Nm Index: usr.sbin/syslogd/syslogd.c =================================================================== RCS file: /home/dcvs/src/usr.sbin/syslogd/syslogd.c,v retrieving revision 1.2 diff -u -r1.2 syslogd.c --- usr.sbin/syslogd/syslogd.c 17 Jun 2003 04:30:03 -0000 1.2 +++ usr.sbin/syslogd/syslogd.c 4 Jul 2004 07:28:09 -0000 @@ -32,7 +32,7 @@ * * @(#) Copyright (c) 1983, 1988, 1993, 1994 The Regents of the University of California. All rights reserved. * @(#)syslogd.c 8.3 (Berkeley) 4/4/94 - * $FreeBSD: src/usr.sbin/syslogd/syslogd.c,v 1.59.2.26 2003/05/20 17:13:53 gshapiro Exp $ + * $FreeBSD: src/usr.sbin/syslogd/syslogd.c,v 1.59.2.29 2004/06/29 10:07:35 dwmalone Exp $ * $DragonFly: src/usr.sbin/syslogd/syslogd.c,v 1.2 2003/06/17 04:30:03 dillon Exp $ */ @@ -49,7 +49,7 @@ * * Defined Constants: * - * MAXLINE -- the maximimum line length that can be handled. + * MAXLINE -- the maximum line length that can be handled. * DEFUPRI -- the default priority for user messages * DEFSPRI -- the default priority for kernel messages * @@ -67,7 +67,7 @@ #define DEFUPRI (LOG_USER|LOG_NOTICE) #define DEFSPRI (LOG_KERN|LOG_CRIT) #define TIMERINTVL 30 /* interval for checking flush, mark */ -#define TTYMSGTIME 1 /* timed out passed to ttymsg */ +#define TTYMSGTIME 1 /* timeout passed to ttymsg */ #include <sys/param.h> #include <sys/ioctl.h> @@ -140,6 +140,8 @@ /* * This structure represents the files that will have log * copies printed. + * We require f_file to be valid if f_type is F_FILE, F_CONSOLE, F_TTY + * or if f_type if F_PIPE and f_pid > 0. */ struct filed { @@ -174,6 +176,8 @@ int f_prevlen; /* length of f_prevline */ int f_prevcount; /* repetition cnt of prevline */ u_int f_repeatcount; /* number of "repeated" msgs */ + int f_flags; /* file-specific flags */ +#define FFLAG_SYNC 0x01 }; /* @@ -253,7 +257,7 @@ static int Debug; /* debug flag */ static int resolve = 1; /* resolve hostname */ static char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ -static char *LocalDomain; /* our local domain name */ +static const char *LocalDomain; /* our local domain name */ static int *finet; /* Internet datagram socket */ static int fklog = -1; /* /dev/klog */ static int Initialized; /* set when we have initialized ourselves */ @@ -297,6 +301,7 @@ static void logmsg(int, const char *, const char *, int); static void log_deadchild(pid_t, int, const char *); static void markit(void); +static int skip_message(const char *, const char *, int); static void printline(const char *, char *); static void printsys(char *); static int p_open(const char *, pid_t *); @@ -359,6 +364,8 @@ KeepKernFac = 1; break; case 'l': + if (strlen(optarg) >= sizeof(sunx.sun_path)) + errx(1, "%s path too long, exiting", optarg); if (nfunix < MAXFUNIX) funixn[nfunix++] = optarg; else @@ -372,6 +379,8 @@ resolve = 0; break; case 'p': /* path */ + if (strlen(optarg) >= sizeof(sunx.sun_path)) + errx(1, "%s path too long, exiting", optarg); funixn[0] = optarg; break; case 'P': /* path for alt. PID */ @@ -386,7 +395,6 @@ case 'v': /* log facility and priority */ LogFacPri++; break; - case '?': default: usage(); } @@ -630,24 +638,31 @@ static void printline(const char *hname, char *msg) { + char *p, *q; + long n; int c, pri; - char *p, *q, line[MAXLINE + 1]; + char line[MAXLINE + 1]; /* test for special codes */ - pri = DEFUPRI; p = msg; + pri = DEFUPRI; if (*p == '<') { - pri = 0; - while (isdigit(*++p)) - pri = 10 * pri + (*p - '0'); - if (*p == '>') - ++p; + errno = 0; + n = strtol(p + 1, &q, 10); + if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { + p = q + 1; + pri = n; + } } if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFUPRI; - /* don't allow users to log kernel messages */ - if (LOG_FAC(pri) == LOG_KERN && !KeepKernFac) + /* + * Don't allow users to log kernel messages. + * NOTE: since LOG_KERN == 0 this will also match + * messages with no facility specified. + */ + if ((pri & LOG_FACMASK) == LOG_KERN && !KeepKernFac) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); q = line; @@ -719,24 +734,31 @@ * Take a raw input line from /dev/klog, format similar to syslog(). */ static void -printsys(char *p) +printsys(char *msg) { - int pri, flags; + char *p, *q; + long n; + int flags, isprintf, pri; flags = ISKERNEL | SYNC_FILE | ADDDATE; /* fsync after write */ + p = msg; pri = DEFSPRI; + isprintf = 1; if (*p == '<') { - pri = 0; - while (isdigit(*++p)) - pri = 10 * pri + (*p - '0'); - if (*p == '>') - ++p; - if ((pri & LOG_FACMASK) == LOG_CONSOLE) - flags |= IGN_CONS; - } else { - /* kernel printf's come out on console */ - flags |= IGN_CONS; + errno = 0; + n = strtol(p + 1, &q, 10); + if (*q == '>' && n >= 0 && n < INT_MAX && errno == 0) { + p = q + 1; + pri = n; + isprintf = 0; + } } + /* + * Kernel printf's and LOG_CONSOLE messages have been displayed + * on the console already. + */ + if (isprintf || (pri & LOG_FACMASK) == LOG_CONSOLE) + flags |= IGN_CONS; if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFSPRI; logmsg(pri, p, LocalHostName, flags); @@ -745,6 +767,50 @@ static time_t now; /* + * Match a program or host name against a specification. + * Return a non-0 value if the message must be ignored + * based on the specification. + */ +static int +skip_message(const char *name, const char *spec, int checkcase) { + const char *s; + char prev, next; + int exclude = 0; + /* Behaviour on explicit match */ + + if (spec == NULL) + return 0; + switch (*spec) { + case '-': + exclude = 1; + /*FALLTHROUGH*/ + case '+': + spec++; + break; + default: + break; + } + if (checkcase) + s = strstr (spec, name); + else + s = strcasestr (spec, name); + + if (s != NULL) { + prev = (s == spec ? ',' : *(s - 1)); + next = *(s + strlen (name)); + + if (prev == ',' && (next == '\0' || next == ',')) + /* Explicit match: skip iff the spec is an + exclusive one. */ + return exclude; + } + + /* No explicit match for this name: skip the message iff + the spec is an inclusive one. */ + return !exclude; +} + +/* * Log a message to the appropriate log files, users, etc. based on * the priority. */ @@ -794,7 +860,8 @@ /* extract program name */ for (i = 0; i < NAME_MAX; i++) { - if (!isprint(msg[i]) || msg[i] == ':' || msg[i] == '[') + if (!isprint(msg[i]) || msg[i] == ':' || msg[i] == '[' || + msg[i] == '/') break; prog[i] = msg[i]; } @@ -831,34 +898,12 @@ continue; /* skip messages with the incorrect hostname */ - if (f->f_host) - switch (f->f_host[0]) { - case '+': - if (strcasecmp(from, f->f_host + 1) != 0) - continue; - break; - case '-': - if (strcasecmp(from, f->f_host + 1) == 0) - continue; - break; - } + if (skip_message(from, f->f_host, 0)) + continue; /* skip messages with the incorrect program name */ - if (f->f_program) - switch (f->f_program[0]) { - case '+': - if (strcmp(prog, f->f_program + 1) != 0) - continue; - break; - case '-': - if (strcmp(prog, f->f_program + 1) == 0) - continue; - break; - default: - if (strcmp(prog, f->f_program) != 0) - continue; - break; - } + if (skip_message(prog, f->f_program, 1)) + continue; /* skip message to console if it has already been printed */ if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) @@ -923,6 +968,7 @@ struct addrinfo *r; int i, l, lsent = 0; char line[MAXLINE + 1], repbuf[80], greetings[200], *wmsg = NULL; + char nul[] = "", space[] = " ", lf[] = "\n", crlf[] = "\r\n"; const char *msgret; v = iov; @@ -933,14 +979,14 @@ f->f_prevhost, ctime(&now)); if (v->iov_len > 0) v++; - v->iov_base = ""; + v->iov_base = nul; v->iov_len = 0; v++; } else { v->iov_base = f->f_lasttime; v->iov_len = 15; v++; - v->iov_base = " "; + v->iov_base = space; v->iov_len = 1; v++; } @@ -982,7 +1028,7 @@ v->iov_base = fp_buf; v->iov_len = strlen(fp_buf); } else { - v->iov_base=""; + v->iov_base = nul; v->iov_len = 0; } v++; @@ -990,7 +1036,7 @@ v->iov_base = f->f_prevhost; v->iov_len = strlen(v->iov_base); v++; - v->iov_base = " "; + v->iov_base = space; v->iov_len = 1; v++; @@ -1026,11 +1072,12 @@ if (strcasecmp(f->f_prevhost, LocalHostName)) l = snprintf(line, sizeof line - 1, "<%d>%.15s Forwarded from %s: %s", - f->f_prevpri, iov[0].iov_base, f->f_prevhost, - iov[5].iov_base); + f->f_prevpri, (char *)iov[0].iov_base, + f->f_prevhost, (char *)iov[5].iov_base); else l = snprintf(line, sizeof line - 1, "<%d>%.15s %s", - f->f_prevpri, iov[0].iov_base, iov[5].iov_base); + f->f_prevpri, (char *)iov[0].iov_base, + (char *)iov[5].iov_base); if (l < 0) l = 0; else if (l > MAXLINE) @@ -1073,8 +1120,7 @@ /* case ENOBUFS: */ /* case ECONNREFUSED: */ default: - dprintf("removing entry\n", e); - (void)close(f->f_file); + dprintf("removing entry\n"); f->f_type = F_UNUSED; break; } @@ -1084,7 +1130,7 @@ case F_FILE: dprintf(" %s\n", f->f_un.f_fname); - v->iov_base = "\n"; + v->iov_base = lf; v->iov_len = 1; if (writev(f->f_file, iov, 7) < 0) { int e = errno; @@ -1092,13 +1138,13 @@ f->f_type = F_UNUSED; errno = e; logerror(f->f_un.f_fname); - } else if (flags & SYNC_FILE) + } else if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) (void)fsync(f->f_file); break; case F_PIPE: dprintf(" %s\n", f->f_un.f_pipe.f_pname); - v->iov_base = "\n"; + v->iov_base = lf; v->iov_len = 1; if (f->f_un.f_pipe.f_pid == 0) { if ((f->f_file = p_open(f->f_un.f_pipe.f_pname, @@ -1129,7 +1175,7 @@ case F_TTY: dprintf(" %s%s\n", _PATH_DEV, f->f_un.f_fname); - v->iov_base = "\r\n"; + v->iov_base = crlf; v->iov_len = 2; errno = 0; /* ttymsg() only sometimes returns an errno */ @@ -1142,7 +1188,7 @@ case F_USERS: case F_WALL: dprintf("\n"); - v->iov_base = "\r\n"; + v->iov_base = crlf; v->iov_len = 2; wallmsg(f, iov); break; @@ -1179,7 +1225,9 @@ while (fread((char *)&ut, sizeof(ut), 1, uf) == 1) { if (ut.ut_name[0] == '\0') continue; - (void)strlcpy(line, ut.ut_line, sizeof(line)); + /* We must use strncpy since ut_* may not be NUL terminated. */ + strncpy(line, ut.ut_line, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; if (f->f_type == F_WALL) { if ((p = ttymsg(iov, 7, line, TTYMSGTIME)) != NULL) { errno = 0; /* already in msg */ @@ -1300,7 +1348,12 @@ logerror(const char *type) { char buf[512]; + static int recursed = 0; + /* If there's an error while trying to log an error, give up. */ + if (recursed) + return; + recursed++; if (errno) (void)snprintf(buf, sizeof buf, "syslogd: %s: %s", type, strerror(errno)); @@ -1309,6 +1362,7 @@ errno = 0; dprintf("%s\n", buf); logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); + recursed--; } static void @@ -1325,8 +1379,10 @@ /* flush any pending output */ if (f->f_prevcount) fprintlog(f, 0, (char *)NULL); - if (f->f_type == F_PIPE) + if (f->f_type == F_PIPE && f->f_un.f_pipe.f_pid > 0) { (void)close(f->f_file); + f->f_un.f_pipe.f_pid = 0; + } } Initialized = was_initialized; if (signo) { @@ -1391,10 +1447,11 @@ (void)close(f->f_file); break; case F_PIPE: - (void)close(f->f_file); - if (f->f_un.f_pipe.f_pid > 0) + if (f->f_un.f_pipe.f_pid > 0) { + (void)close(f->f_file); deadq_enter(f->f_un.f_pipe.f_pid, f->f_un.f_pipe.f_pname); + } f->f_un.f_pipe.f_pid = 0; break; } @@ -1457,7 +1514,8 @@ if (*p == '@') p = LocalHostName; for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { - if (!isalnum(*p) && *p != '.' && *p != '-') + if (!isalnum(*p) && *p != '.' && *p != '-' + && *p != ',') break; host[i] = *p++; } @@ -1479,9 +1537,8 @@ prog[i] = 0; continue; } - for (p = strchr(cline, '\0'); isspace(*--p);) - continue; - *++p = '\0'; + for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--) + cline[i] = '\0'; f = (struct filed *)calloc(1, sizeof(*f)); if (f == NULL) { logerror("calloc"); @@ -1555,7 +1612,7 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host) { struct addrinfo hints, *res; - int error, i, pri; + int error, i, pri, syncfile; const char *p, *q; char *bp; char buf[MAXLINE], ebuf[100]; @@ -1649,6 +1706,10 @@ pri = LOG_PRIMASK + 1; pri_cmp = PRI_LT | PRI_EQ | PRI_GT; } else { + /* Ignore trailing spaces. */ + for (i = strlen(buf) - 1; i >= 0 && buf[i] == ' '; i--) + buf[i] = '\0'; + pri = decode(buf, prioritynames); if (pri < 0) { (void)snprintf(ebuf, sizeof ebuf, @@ -1699,6 +1760,12 @@ while (*p == '\t' || *p == ' ') p++; + if (*p == '-') { + syncfile = 0; + p++; + } else + syncfile = 1; + switch (*p) { case '@': (void)strlcpy(f->f_un.f_forw.f_hname, ++p, @@ -1722,6 +1789,8 @@ logerror(p); break; } + if (syncfile) + f->f_flags |= FFLAG_SYNC; if (isatty(f->f_file)) { if (strcmp(p, ctty) == 0) f->f_type = F_CONSOLE; @@ -2209,9 +2278,10 @@ * opposed to a FILE *. */ static int -p_open(const char *prog, pid_t *pid) +p_open(const char *prog, pid_t *rpid) { int pfd[2], nulldesc, i; + pid_t pid; sigset_t omask, mask; char *argv[4]; /* sh -c cmd NULL */ char errmsg[200]; @@ -2226,7 +2296,7 @@ sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGHUP); sigprocmask(SIG_BLOCK, &mask, &omask); - switch ((*pid = fork())) { + switch ((pid = fork())) { case -1: sigprocmask(SIG_SETMASK, &omask, 0); close(nulldesc); @@ -2284,9 +2354,10 @@ (void)snprintf(errmsg, sizeof errmsg, "Warning: cannot change pipe to PID %d to " "non-blocking behaviour.", - (int)*pid); + (int)pid); logerror(errmsg); } + *rpid = pid; return (pfd[1]); }
Attachment:
pgp00000.pgp
Description: PGP signature