Skip site navigation (1)Skip section navigation (2)
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>