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
--LQksG6bCIzRHxTLp Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable 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 :) >=20 > 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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=3Dno, 1=3Dnumeric, 2=3Dnames */ int KeepKernFac =3D 0; /* Keep remotely logged kernel facility */ =20 +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 =3D 0; struct sockaddr_un sunx, fromunix; struct sockaddr_storage frominet; + fd_set *fdsr =3D 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 =3D 1; socklen_t len; =20 @@ -397,17 +403,18 @@ endservent(); =20 consfile.f_type =3D 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 =3D strchr(LocalHostName, '.')) !=3D NULL) { *p++ =3D '\0'; LocalDomain =3D p; } else LocalDomain =3D ""; - (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 =3D 0; i < nfunix; i++) { memset(&sunx, 0, sizeof(sunx)); sunx.sun_family =3D 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] =3D socket(AF_UNIX, SOCK_DGRAM, 0); if (funix[i] < 0 || bind(funix[i], (struct sockaddr *)&sunx, @@ -490,53 +497,65 @@ tvp =3D &tv; tv.tv_sec =3D tv.tv_usec =3D 0; =20 + if (fklog !=3D -1 && fklog > fdsrmax) + fdsrmax =3D fklog; + if (finet && !SecureMode) { + for (i =3D 0; i < *finet; i++) { + if (finet[i+1] !=3D -1 && finet[i+1] > fdsrmax) + fdsrmax =3D finet[i+1]; + } + } + for (i =3D 0; i < nfunix; i++) { + if (funix[i] !=3D -1 && funix[i] > fdsrmax) + fdsrmax =3D funix[i]; + } + + fdsr =3D (fd_set *)calloc(howmany(fdsrmax+1, NFDBITS), + sizeof(fd_mask)); + if (fdsr =3D=3D NULL) + errx(1, "calloc fd_set"); + for (;;) { - fd_set readfds; - int nfds =3D 0; + if (MarkSet) + markit(); + if (WantDie) + die(WantDie); =20 - FD_ZERO(&readfds); - if (fklog !=3D -1) { - FD_SET(fklog, &readfds); - if (fklog > nfds) - nfds =3D fklog; - } + bzero(fdsr, howmany(fdsrmax+1, NFDBITS) * + sizeof(fd_mask)); + + if (fklog !=3D -1) + FD_SET(fklog, fdsr); if (finet && !SecureMode) { for (i =3D 0; i < *finet; i++) { - FD_SET(finet[i+1], &readfds); - if (finet[i+1] > nfds) - nfds =3D finet[i+1]; + if (finet[i+1] !=3D -1) + FD_SET(finet[i+1], fdsr); } } for (i =3D 0; i < nfunix; i++) { - if (funix[i] !=3D -1) { - FD_SET(funix[i], &readfds); - if (funix[i] > nfds) - nfds =3D funix[i]; - } + if (funix[i] !=3D -1) + FD_SET(funix[i], fdsr); } =20 - /*dprintf("readfds =3D %#x\n", readfds);*/ - nfds =3D select(nfds+1, &readfds, (fd_set *)NULL, - (fd_set *)NULL, tvp); - if (nfds =3D=3D 0) { + i =3D select(fdsrmax+1, fdsr, NULL, NULL, tvp); + switch (i) { + case 0: if (tvp) { tvp =3D NULL; if (ppid !=3D 1) kill(ppid, SIGALRM); } continue; - } - if (nfds < 0) { + case -1: if (errno !=3D EINTR) logerror("select"); continue; } - /*dprintf("got a message (%d, %#x)\n", nfds, readfds);*/ - if (fklog !=3D -1 && FD_ISSET(fklog, &readfds)) + if (fklog !=3D -1 && FD_ISSET(fklog, fdsr)) readklog(); if (finet && !SecureMode) { for (i =3D 0; i < *finet; i++) { - if (FD_ISSET(finet[i+1], &readfds)) { + if (FD_ISSET(finet[i+1], fdsr)) { len =3D sizeof(frominet); l =3D recvfrom(finet[i+1], line, MAXLINE, 0, (struct sockaddr *)&frominet, @@ -553,7 +572,7 @@ } } for (i =3D 0; i < nfunix; i++) { - if (funix[i] !=3D -1 && FD_ISSET(funix[i], &readfds)) { + if (funix[i] !=3D -1 && FD_ISSET(funix[i], fdsr)) { len =3D sizeof(fromunix); l =3D recvfrom(funix[i], line, MAXLINE, 0, (struct sockaddr *)&fromunix, &len); @@ -565,6 +584,8 @@ } } } + if (fdsr) + free(fdsr); } =20 static void @@ -843,7 +864,7 @@ if ((flags & MARK) =3D=3D 0 && msglen =3D=3D 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 =3D 0; f->f_prevpri =3D 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] =3D '\0'; + strlcpy(f->f_lasttime, timestamp, 16); + strlcpy(f->f_prevhost, from, + sizeof(f->f_prevhost)); if (msglen < MAXSVLINE) { f->f_prevlen =3D 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] =3D 0; @@ -968,8 +988,8 @@ v->iov_len =3D strlen(msg); } else if (f->f_prevcount > 1) { v->iov_base =3D repbuf; - v->iov_len =3D sprintf(repbuf, "last message repeated %d times", - f->f_prevcount); + v->iov_len =3D snprintf(repbuf, sizeof repbuf, + "last message repeated %d times", f->f_prevcount); } else { v->iov_base =3D f->f_prevline; v->iov_len =3D f->f_prevlen; @@ -1124,8 +1144,7 @@ while (fread((char *)&ut, sizeof(ut), 1, uf) =3D=3D 1) { if (ut.ut_name[0] =3D=3D '\0') continue; - strncpy(line, ut.ut_line, sizeof(ut.ut_line)); - line[sizeof(ut.ut_line)] =3D '\0'; + strlcpy(line, ut.ut_line, sizeof(line)); if (f->f_type =3D=3D F_WALL) { if ((p =3D ttymsg(iov, 7, line, TTYMSGTIME)) !=3D NULL) { errno =3D 0; /* already in msg */ @@ -1227,56 +1246,17 @@ } =20 void -domark(signo) +dodie(signo) int signo; { - struct filed *f; - dq_t q; - - now =3D time((time_t *)NULL); - MarkSeq +=3D TIMERINTVL; - if (MarkSeq >=3D MarkInterval) { - logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK); - MarkSeq =3D 0; - } - - for (f =3D Files; f; f =3D f->f_next) { - if (f->f_prevcount && now >=3D 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 =3D TAILQ_FIRST(&deadq_head); q !=3D NULL; q =3D TAILQ_NEXT(q, dq_= entries)) - switch (q->dq_timeout) { - case 0: - /* Already signalled once, try harder now. */ - if (kill(q->dq_pid, SIGKILL) !=3D 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) !=3D 0) - (void)deadq_remove(q->dq_pid); - /* FALLTHROUGH */ - - default: - q->dq_timeout--; - } + WantDie =3D signo; +} =20 - (void)alarm(TIMERINTVL); +void +domark(signo) + int signo; +{ + MarkSet =3D 1; } =20 /* @@ -1319,7 +1299,7 @@ Initialized =3D 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 =3D 0; logerror(buf); } @@ -1393,8 +1373,8 @@ * Foreach line in the conf table, open that file. */ f =3D NULL; - strcpy(host, "*"); - strcpy(prog, "*"); + strlcpy(host, "*", sizeof(host)); + strlcpy(prog, "*", sizeof(prog)); while (fgets(cline, sizeof(cline), cf) !=3D NULL) { /* * check for end-of-section, comments, strip off trailing @@ -1414,7 +1394,7 @@ host[0] =3D *p++; while (isspace(*p)) p++; if ((!*p) || (*p =3D=3D '*')) { - strcpy(host, "*"); + strlcpy(host, "*", sizeof(host)); continue; } if (*p =3D=3D '@') @@ -1431,7 +1411,7 @@ p++; while (isspace(*p)) p++; if ((!*p) || (*p =3D=3D '*')) { - strcpy(prog, "*"); + strlcpy(prog, "*", sizeof(prog)); continue; } for (i =3D 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] =3D '\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 =3D family; hints.ai_socktype =3D SOCK_DGRAM; @@ -1656,16 +1635,17 @@ f->f_type =3D F_CONSOLE; else f->f_type =3D 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 =3D F_FILE; } break; =20 case '|': f->f_un.f_pipe.f_pid =3D 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 =3D F_PIPE; break; =20 @@ -1720,6 +1700,59 @@ return (-1); } =20 +void +markit(void) +{ + struct filed *f; + dq_t q; + + now =3D time((time_t *)NULL); + MarkSeq +=3D TIMERINTVL; + if (MarkSeq >=3D MarkInterval) { + logmsg(LOG_INFO, "-- MARK --", + LocalHostName, ADDDATE|MARK); + MarkSeq =3D 0; + } + + for (f =3D Files; f; f =3D f->f_next) { + if (f->f_prevcount && now >=3D 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 =3D TAILQ_FIRST(&deadq_head); q !=3D NULL; q =3D TAILQ_NEXT(q, dq_= entries)) + switch (q->dq_timeout) { + case 0: + /* Already signalled once, try harder now. */ + if (kill(q->dq_pid, SIGKILL) !=3D 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) !=3D 0) + (void)deadq_remove(q->dq_pid); + /* FALLTHROUGH */ + + default: + q->dq_timeout--; + } + MarkSet =3D 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 =3D=3D 0) errx(1, "timed out waiting for child"); else - exit(0); + _exit(0); } =20 /* --LQksG6bCIzRHxTLp Content-Type: application/pgp-signature Content-Disposition: inline -----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----- --LQksG6bCIzRHxTLp-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010724011213.A4758>