Date: Tue, 24 Jul 2001 01:12:13 -0700 From: Kris Kennaway <kris@obsecurity.org> To: Kris Kennaway <kris@obsecurity.org> Cc: audit@FreeBSD.ORG Subject: Re: syslogd signal/string patch Message-ID: <20010724011213.A4758@xor.obsecurity.org> In-Reply-To: <20010724004956.A4293@xor.obsecurity.org>; from kris@obsecurity.org on Tue, Jul 24, 2001 at 12:49:56AM -0700 References: <20010724003529.A3687@xor.obsecurity.org> <20010724004956.A4293@xor.obsecurity.org>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
On Tue, Jul 24, 2001 at 12:49:56AM -0700, Kris Kennaway wrote:
> On Tue, Jul 24, 2001 at 12:35:29AM -0700, Kris Kennaway wrote:
> > It seems to work :)
>
> No it doesn't (looks like the child process is spinning on the CPU).
Stupid off-by-one bug :)
I also changed an exit() in a signal handler introduced by FreeBSD to
_exit(), which I think is correct. There's an errx() in there as
well; is that okay?
Kris
Index: syslogd.c
===================================================================
RCS file: /mnt/ncvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.79
diff -u -r1.79 syslogd.c
--- syslogd.c 2001/07/02 15:26:47 1.79
+++ syslogd.c 2001/07/24 08:10:42
@@ -282,6 +282,9 @@
/* 0=no, 1=numeric, 2=names */
int KeepKernFac = 0; /* Keep remotely logged kernel facility */
+sig_atomic_t MarkSet;
+sig_atomic_t WantDie;
+
int allowaddr __P((char *));
void cfline __P((char *, struct filed *, char *, char *));
char *cvthname __P((struct sockaddr *));
@@ -289,6 +292,7 @@
int deadq_remove __P((pid_t));
int decode __P((const char *, CODE *));
void die __P((int));
+void dodie __P((int));
void domark __P((int));
void fprintlog __P((struct filed *, int, char *));
int* socksetup __P((int));
@@ -296,6 +300,7 @@
void logerror __P((const char *));
void logmsg __P((int, char *, char *, int));
void log_deadchild __P((pid_t, int, const char *));
+void markit __P((void));
void printline __P((char *, char *));
void printsys __P((char *));
int p_open __P((char *, pid_t *));
@@ -314,14 +319,15 @@
int argc;
char *argv[];
{
- int ch, i, l;
+ int ch, i, l, fdsrmax = 0;
struct sockaddr_un sunx, fromunix;
struct sockaddr_storage frominet;
+ fd_set *fdsr = NULL;
FILE *fp;
char *p, *hname, line[MAXLINE + 1];
- struct timeval tv, *tvp;
struct sigaction sact;
sigset_t mask;
+ struct timeval tv, *tvp;
pid_t ppid = 1;
socklen_t len;
@@ -397,17 +403,18 @@
endservent();
consfile.f_type = F_CONSOLE;
- (void)strcpy(consfile.f_un.f_fname, ctty + sizeof _PATH_DEV - 1);
+ (void)strlcpy(consfile.f_un.f_fname, ctty + sizeof _PATH_DEV - 1,
+ sizeof(consfile.f_un.f_fname));
(void)gethostname(LocalHostName, sizeof(LocalHostName));
if ((p = strchr(LocalHostName, '.')) != NULL) {
*p++ = '\0';
LocalDomain = p;
} else
LocalDomain = "";
- (void)strcpy(bootfile, getbootfile());
- (void)signal(SIGTERM, die);
- (void)signal(SIGINT, Debug ? die : SIG_IGN);
- (void)signal(SIGQUIT, Debug ? die : SIG_IGN);
+ (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile));
+ (void)signal(SIGTERM, dodie);
+ (void)signal(SIGINT, Debug ? dodie : SIG_IGN);
+ (void)signal(SIGQUIT, Debug ? dodie : SIG_IGN);
/*
* We don't want the SIGCHLD and SIGHUP handlers to interfere
* with each other; they are likely candidates for being called
@@ -432,7 +439,7 @@
for (i = 0; i < nfunix; i++) {
memset(&sunx, 0, sizeof(sunx));
sunx.sun_family = AF_UNIX;
- (void)strncpy(sunx.sun_path, funixn[i], sizeof(sunx.sun_path));
+ (void)strlcpy(sunx.sun_path, funixn[i], sizeof(sunx.sun_path));
funix[i] = socket(AF_UNIX, SOCK_DGRAM, 0);
if (funix[i] < 0 ||
bind(funix[i], (struct sockaddr *)&sunx,
@@ -490,53 +497,65 @@
tvp = &tv;
tv.tv_sec = tv.tv_usec = 0;
+ if (fklog != -1 && fklog > fdsrmax)
+ fdsrmax = fklog;
+ if (finet && !SecureMode) {
+ for (i = 0; i < *finet; i++) {
+ if (finet[i+1] != -1 && finet[i+1] > fdsrmax)
+ fdsrmax = finet[i+1];
+ }
+ }
+ for (i = 0; i < nfunix; i++) {
+ if (funix[i] != -1 && funix[i] > fdsrmax)
+ fdsrmax = funix[i];
+ }
+
+ fdsr = (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS),
+ sizeof(fd_mask));
+ if (fdsr == NULL)
+ errx(1, "calloc fd_set");
+
for (;;) {
- fd_set readfds;
- int nfds = 0;
+ if (MarkSet)
+ markit();
+ if (WantDie)
+ die(WantDie);
- FD_ZERO(&readfds);
- if (fklog != -1) {
- FD_SET(fklog, &readfds);
- if (fklog > nfds)
- nfds = fklog;
- }
+ bzero(fdsr, howmany(fdsrmax+1, NFDBITS) *
+ sizeof(fd_mask));
+
+ if (fklog != -1)
+ FD_SET(fklog, fdsr);
if (finet && !SecureMode) {
for (i = 0; i < *finet; i++) {
- FD_SET(finet[i+1], &readfds);
- if (finet[i+1] > nfds)
- nfds = finet[i+1];
+ if (finet[i+1] != -1)
+ FD_SET(finet[i+1], fdsr);
}
}
for (i = 0; i < nfunix; i++) {
- if (funix[i] != -1) {
- FD_SET(funix[i], &readfds);
- if (funix[i] > nfds)
- nfds = funix[i];
- }
+ if (funix[i] != -1)
+ FD_SET(funix[i], fdsr);
}
- /*dprintf("readfds = %#x\n", readfds);*/
- nfds = select(nfds+1, &readfds, (fd_set *)NULL,
- (fd_set *)NULL, tvp);
- if (nfds == 0) {
+ i = select(fdsrmax+1, fdsr, NULL, NULL, tvp);
+ switch (i) {
+ case 0:
if (tvp) {
tvp = NULL;
if (ppid != 1)
kill(ppid, SIGALRM);
}
continue;
- }
- if (nfds < 0) {
+ case -1:
if (errno != EINTR)
logerror("select");
continue;
}
- /*dprintf("got a message (%d, %#x)\n", nfds, readfds);*/
- if (fklog != -1 && FD_ISSET(fklog, &readfds))
+ if (fklog != -1 && FD_ISSET(fklog, fdsr))
readklog();
if (finet && !SecureMode) {
for (i = 0; i < *finet; i++) {
- if (FD_ISSET(finet[i+1], &readfds)) {
+ if (FD_ISSET(finet[i+1], fdsr)) {
len = sizeof(frominet);
l = recvfrom(finet[i+1], line, MAXLINE,
0, (struct sockaddr *)&frominet,
@@ -553,7 +572,7 @@
}
}
for (i = 0; i < nfunix; i++) {
- if (funix[i] != -1 && FD_ISSET(funix[i], &readfds)) {
+ if (funix[i] != -1 && FD_ISSET(funix[i], fdsr)) {
len = sizeof(fromunix);
l = recvfrom(funix[i], line, MAXLINE, 0,
(struct sockaddr *)&fromunix, &len);
@@ -565,6 +584,8 @@
}
}
}
+ if (fdsr)
+ free(fdsr);
}
static void
@@ -843,7 +864,7 @@
if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
!strcmp(msg, f->f_prevline) &&
!strcasecmp(from, f->f_prevhost)) {
- (void)strncpy(f->f_lasttime, timestamp, 15);
+ (void)strlcpy(f->f_lasttime, timestamp, 16);
f->f_prevcount++;
dprintf("msg repeated %d times, %ld sec of %d\n",
f->f_prevcount, (long)(now - f->f_time),
@@ -864,13 +885,12 @@
fprintlog(f, 0, (char *)NULL);
f->f_repeatcount = 0;
f->f_prevpri = pri;
- (void)strncpy(f->f_lasttime, timestamp, 15);
- (void)strncpy(f->f_prevhost, from,
- sizeof(f->f_prevhost)-1);
- f->f_prevhost[sizeof(f->f_prevhost)-1] = '\0';
+ strlcpy(f->f_lasttime, timestamp, 16);
+ strlcpy(f->f_prevhost, from,
+ sizeof(f->f_prevhost));
if (msglen < MAXSVLINE) {
f->f_prevlen = msglen;
- (void)strcpy(f->f_prevline, msg);
+ strlcpy(f->f_prevline, msg, sizeof(f->f_prevline));
fprintlog(f, flags, (char *)NULL);
} else {
f->f_prevline[0] = 0;
@@ -968,8 +988,8 @@
v->iov_len = strlen(msg);
} else if (f->f_prevcount > 1) {
v->iov_base = repbuf;
- v->iov_len = sprintf(repbuf, "last message repeated %d times",
- f->f_prevcount);
+ v->iov_len = snprintf(repbuf, sizeof repbuf,
+ "last message repeated %d times", f->f_prevcount);
} else {
v->iov_base = f->f_prevline;
v->iov_len = f->f_prevlen;
@@ -1124,8 +1144,7 @@
while (fread((char *)&ut, sizeof(ut), 1, uf) == 1) {
if (ut.ut_name[0] == '\0')
continue;
- strncpy(line, ut.ut_line, sizeof(ut.ut_line));
- line[sizeof(ut.ut_line)] = '\0';
+ strlcpy(line, ut.ut_line, sizeof(line));
if (f->f_type == F_WALL) {
if ((p = ttymsg(iov, 7, line, TTYMSGTIME)) != NULL) {
errno = 0; /* already in msg */
@@ -1227,56 +1246,17 @@
}
void
-domark(signo)
+dodie(signo)
int signo;
{
- struct filed *f;
- dq_t q;
-
- now = time((time_t *)NULL);
- MarkSeq += TIMERINTVL;
- if (MarkSeq >= MarkInterval) {
- logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
- MarkSeq = 0;
- }
-
- for (f = Files; f; f = f->f_next) {
- if (f->f_prevcount && now >= REPEATTIME(f)) {
- dprintf("flush %s: repeated %d times, %d sec.\n",
- TypeNames[f->f_type], f->f_prevcount,
- repeatinterval[f->f_repeatcount]);
- fprintlog(f, 0, (char *)NULL);
- BACKOFF(f);
- }
- }
-
- /* Walk the dead queue, and see if we should signal somebody. */
- for (q = TAILQ_FIRST(&deadq_head); q != NULL; q = TAILQ_NEXT(q, dq_entries))
- switch (q->dq_timeout) {
- case 0:
- /* Already signalled once, try harder now. */
- if (kill(q->dq_pid, SIGKILL) != 0)
- (void)deadq_remove(q->dq_pid);
- break;
-
- case 1:
- /*
- * Timed out on dead queue, send terminate
- * signal. Note that we leave the removal
- * from the dead queue to reapchild(), which
- * will also log the event (unless the process
- * didn't even really exist, in case we simply
- * drop it from the dead queue).
- */
- if (kill(q->dq_pid, SIGTERM) != 0)
- (void)deadq_remove(q->dq_pid);
- /* FALLTHROUGH */
-
- default:
- q->dq_timeout--;
- }
+ WantDie = signo;
+}
- (void)alarm(TIMERINTVL);
+void
+domark(signo)
+ int signo;
+{
+ MarkSet = 1;
}
/*
@@ -1319,7 +1299,7 @@
Initialized = was_initialized;
if (signo) {
dprintf("syslogd: exiting on signal %d\n", signo);
- (void)sprintf(buf, "exiting on signal %d", signo);
+ (void)snprintf(buf, sizeof buf, "exiting on signal %d", signo);
errno = 0;
logerror(buf);
}
@@ -1393,8 +1373,8 @@
* Foreach line in the conf table, open that file.
*/
f = NULL;
- strcpy(host, "*");
- strcpy(prog, "*");
+ strlcpy(host, "*", sizeof(host));
+ strlcpy(prog, "*", sizeof(prog));
while (fgets(cline, sizeof(cline), cf) != NULL) {
/*
* check for end-of-section, comments, strip off trailing
@@ -1414,7 +1394,7 @@
host[0] = *p++;
while (isspace(*p)) p++;
if ((!*p) || (*p == '*')) {
- strcpy(host, "*");
+ strlcpy(host, "*", sizeof(host));
continue;
}
if (*p == '@')
@@ -1431,7 +1411,7 @@
p++;
while (isspace(*p)) p++;
if ((!*p) || (*p == '*')) {
- strcpy(prog, "*");
+ strlcpy(prog, "*", sizeof(prog));
continue;
}
for (i = 0; i < NAME_MAX; i++) {
@@ -1629,9 +1609,8 @@
switch (*p)
{
case '@':
- (void)strncpy(f->f_un.f_forw.f_hname, ++p,
- sizeof(f->f_un.f_forw.f_hname)-1);
- f->f_un.f_forw.f_hname[sizeof(f->f_un.f_forw.f_hname)-1] = '\0';
+ (void)strlcpy(f->f_un.f_forw.f_hname, ++p,
+ sizeof(f->f_un.f_forw.f_hname));
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
@@ -1656,16 +1635,17 @@
f->f_type = F_CONSOLE;
else
f->f_type = F_TTY;
- (void)strcpy(f->f_un.f_fname, p + sizeof _PATH_DEV - 1);
+ (void)strlcpy(f->f_un.f_fname, p + sizeof _PATH_DEV - 1,
+ sizeof(f->f_un.f_fname));
} else {
- (void)strcpy(f->f_un.f_fname, p);
+ (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname));
f->f_type = F_FILE;
}
break;
case '|':
f->f_un.f_pipe.f_pid = 0;
- (void)strcpy(f->f_un.f_pipe.f_pname, p + 1);
+ (void)strlcpy(f->f_un.f_fname, p + 1, sizeof(f->f_un.f_fname));
f->f_type = F_PIPE;
break;
@@ -1720,6 +1700,59 @@
return (-1);
}
+void
+markit(void)
+{
+ struct filed *f;
+ dq_t q;
+
+ now = time((time_t *)NULL);
+ MarkSeq += TIMERINTVL;
+ if (MarkSeq >= MarkInterval) {
+ logmsg(LOG_INFO, "-- MARK --",
+ LocalHostName, ADDDATE|MARK);
+ MarkSeq = 0;
+ }
+
+ for (f = Files; f; f = f->f_next) {
+ if (f->f_prevcount && now >= REPEATTIME(f)) {
+ dprintf("flush %s: repeated %d times, %d sec.\n",
+ TypeNames[f->f_type], f->f_prevcount,
+ repeatinterval[f->f_repeatcount]);
+ fprintlog(f, 0, (char *)NULL);
+ BACKOFF(f);
+ }
+ }
+
+ /* Walk the dead queue, and see if we should signal somebody. */
+ for (q = TAILQ_FIRST(&deadq_head); q != NULL; q = TAILQ_NEXT(q, dq_entries))
+ switch (q->dq_timeout) {
+ case 0:
+ /* Already signalled once, try harder now. */
+ if (kill(q->dq_pid, SIGKILL) != 0)
+ (void)deadq_remove(q->dq_pid);
+ break;
+
+ case 1:
+ /*
+ * Timed out on dead queue, send terminate
+ * signal. Note that we leave the removal
+ * from the dead queue to reapchild(), which
+ * will also log the event (unless the process
+ * didn't even really exist, in case we simply
+ * drop it from the dead queue).
+ */
+ if (kill(q->dq_pid, SIGTERM) != 0)
+ (void)deadq_remove(q->dq_pid);
+ /* FALLTHROUGH */
+
+ default:
+ q->dq_timeout--;
+ }
+ MarkSet = 0;
+ (void)alarm(TIMERINTVL);
+}
+
/*
* fork off and become a daemon, but wait for the child to come online
* before returing to the parent, or we get disk thrashing at boot etc.
@@ -1789,7 +1822,7 @@
if (left == 0)
errx(1, "timed out waiting for child");
else
- exit(0);
+ _exit(0);
}
/*
[-- Attachment #2 --]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (FreeBSD)
Comment: For info see http://www.gnupg.org
iD8DBQE7XS3cWry0BWjoQKURAgCEAJ0Q7n6LQGJ70vAUs4Vsw6doQw99ZACfaKtT
O6Pg/euqMlhnO+Rqqr2c7d0=
=3mgD
-----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010724011213.A4758>
