[rtems-libbsd commit] SYSLOG(3): Replace implementation

Sebastian Huber sebh at rtems.org
Thu Oct 9 12:48:03 UTC 2014


Module:    rtems-libbsd
Branch:    master
Commit:    d5eac12255b03d0da1c7509ca4b61c7ab7fdf290
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=d5eac12255b03d0da1c7509ca4b61c7ab7fdf290

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Oct  9 14:34:13 2014 +0200

SYSLOG(3): Replace implementation

Avoid potential buffer overflows on the stack.  Expand the %m in the
format string.

---

 rtemsbsd/rtems/syslog.c          |  307 +++++++++++++++++++-------------------
 testsuite/syscalls01/test_main.c |   24 +++
 2 files changed, 177 insertions(+), 154 deletions(-)

diff --git a/rtemsbsd/rtems/syslog.c b/rtemsbsd/rtems/syslog.c
index 7d3128b..2342023 100644
--- a/rtemsbsd/rtems/syslog.c
+++ b/rtemsbsd/rtems/syslog.c
@@ -1,194 +1,193 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_rtems
+ *
+ * @brief TODO.
+ */
+
 /*
- * RTEMS version of syslog and associated routines
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <machine/rtems-bsd-user-space.h>
+#include <machine/rtems-bsd-program.h>
 
-#include <rtems.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <errno.h>
 #include <syslog.h>
-#include <rtems/bsd/sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
+#include <errno.h>
+#include <stdio.h>
 #include <string.h>
 
-#include <unistd.h>
-
-#include <machine/rtems-bsd-printf-to-iprintf.h>
-
-static int LogStatus = LOG_CONS;
-static const char *LogTag = "syslog";
-static int LogFacility = LOG_USER;
-static int LogMask = 0xff;
-
-static int LogFd = -1;
-static rtems_id LogSemaphore;
-extern struct in_addr rtems_bsdnet_log_host_address;
+typedef struct {
+  int mask;
+} rtems_bsd_syslog_context;
+
+/* FIXME: This should be thread specific */
+static rtems_bsd_syslog_context rtems_bsd_syslog_instance = {
+	.mask = LOG_UPTO(LOG_DEBUG)
+};
+
+static const char * const rtems_bsd_syslog_priorities[] = {
+	[LOG_EMERG] = "emerg",
+	[LOG_ALERT] = "alert",
+	[LOG_CRIT] = "crit",
+	[LOG_ERR] = "err",
+	[LOG_WARNING] = "warning",
+	[LOG_NOTICE] = "notice",
+	[LOG_INFO] = "info",
+	[LOG_DEBUG] = "debug"
+};
+
+static rtems_bsd_syslog_context *
+rtems_bsd_syslog_get_context(void)
+{
+	return &rtems_bsd_syslog_instance;
+}
 
-#define SYSLOG_PORT	514
+static void
+rtems_bsd_syslog_format_buffer_overflow(void)
+{
+	fputs("err: syslog: format buffer overflow\n", stderr);
+}
 
 void
-syslog (int pri, const char *fmt, ...)
+syslog(int priority, const char *format, ...)
 {
 	va_list ap;
 
-	va_start (ap, fmt);
-	vsyslog (pri, fmt, ap);
-	va_end (ap);
+	va_start(ap, format);
+	vsyslog(priority, format, ap);
+	va_end(ap);
 }
 
-/*
- * FIXME: Should cbuf be static?  It could be if we put the mutex
- *        around the entire body of this routine.  Then we wouldn't
- *        have to worry about blowing stacks with a local variable
- *        that large.  Could make cbuf bigger, too.
- */
 void
-vsyslog (int pri, const char *fmt, va_list ap)
+vsyslog(int priority, const char *format, va_list ap)
 {
-	int cnt;
-	char *cp;
-	char *msgp, cbuf[200];
-	int sent;
-
-	if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
-		syslog (LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID,
-								"syslog: unknown facility/priority: %#x", pri);
-		pri &= LOG_PRIMASK|LOG_FACMASK;
+	rtems_bsd_syslog_context *ctx = rtems_bsd_syslog_get_context();
+	int pri = LOG_PRI(priority);
+	char fmt[128];
+	char buf[128];
+	const char *src;
+	char *dst;
+	size_t rem;
+	char *m;
+	int n;
+	size_t len;
+
+	if ((LOG_MASK(pri) & ctx->mask) == 0) {
+		return;
 	}
 
-	if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
-		return;
+	/* Expand the %m in the format string and add a newline character */
 
-	if ((pri & LOG_FACMASK) == 0)
-		pri |= LogFacility;
+	src = format;
+	dst = &fmt[0];
+	rem = sizeof(fmt) - 2;
 
-	cnt = sprintf (cbuf, "<%d>", pri);
-	cp = msgp = cbuf + cnt;
-	if (LogTag) {
-		const char *lp = LogTag;
-		while ((*cp = *lp++) != '\0')
-			cp++;
-	}
-	if (LogStatus & LOG_PID) {
-		rtems_id tid;
-		rtems_task_ident (RTEMS_SELF, 0, &tid);
-		cnt = sprintf (cp, "[%#lx]", (unsigned long)tid);
-		cp += cnt;
-	}
-	if (LogTag) {
-		*cp++ = ':';
-		*cp++ = ' ';
-	}
-	cnt = vsprintf (cp, fmt, ap);
-	cnt += cp - cbuf;
-	if (cbuf[cnt-1] == '\n')
-		cbuf[--cnt] = '\0';
-
-	if (LogStatus & LOG_PERROR)
-		printf ("%s\n", cbuf);
-
-	/*
-	 * Grab the mutex
-	 */
-	sent = 0;
-	if ((rtems_bsdnet_log_host_address.s_addr != INADDR_ANY)
-	 && (LogFd >= 0)
-	 && (rtems_semaphore_obtain (LogSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL)) {
-		/*
-		 * Set the destination address/port
-		 */
-		struct sockaddr_in farAddress;
-		farAddress.sin_family = AF_INET;
-		farAddress.sin_port = htons (SYSLOG_PORT);
-		farAddress.sin_addr = rtems_bsdnet_log_host_address;
-		memset (farAddress.sin_zero, '\0', sizeof farAddress.sin_zero);
-
-		/*
-		 * Send the message
-		 */
-		if (sendto (LogFd, cbuf, cnt, 0, (struct sockaddr *)&farAddress, sizeof farAddress) >= 0)
-			sent = 1;
-		rtems_semaphore_release (LogSemaphore);
+	while ((m = strstr(src, "%m")) != NULL) {
+		size_t c = m - src;
+
+		if (c > rem) {
+			rtems_bsd_syslog_format_buffer_overflow();
+			return;
+		}
+
+		memcpy(dst, src, c);
+		dst += c;
+		src += c + 2;
+		rem -= c;
+
+		n = sniprintf(dst, rem, "%s", strerror(errno));
+		if (n > rem || n < 0) {
+			rtems_bsd_syslog_format_buffer_overflow();
+			return;
+		}
+
+		dst += (size_t) n;
+		rem -= (size_t) n;
 	}
-	if (!sent && (LogStatus & LOG_CONS) && !(LogStatus & LOG_PERROR))
-		printf ("%s\n", msgp);
-}
 
-void
-openlog (const char *ident, int logstat, int logfac)
-{
-	rtems_status_code sc;
-	struct sockaddr_in myAddress;
-
-	if (ident != NULL)
-		LogTag = ident;
-	LogStatus = logstat;
-	if (logfac != 0 && (logfac & ~LOG_FACMASK) == 0)
-		LogFacility = logfac;
-
-	/*
-	 * Create the socket
-	 */
-	if ((LogFd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
-		printf ("Can't create syslog socket: %d\n", errno);
+	len = strlen(src);
+	if (len > rem) {
+		rtems_bsd_syslog_format_buffer_overflow();
 		return;
 	}
 
-	/*
-	 * Bind socket to name
-	 */
-	myAddress.sin_family = AF_INET;
-	myAddress.sin_addr.s_addr = INADDR_ANY;
-	myAddress.sin_port = 0;
-	memset (myAddress.sin_zero, '\0', sizeof myAddress.sin_zero);
-	if (bind (LogFd, (struct sockaddr *)&myAddress, sizeof (myAddress)) < 0) {
-		close (LogFd);
-		LogFd = -1;
-		printf ("Can't bind syslog socket: %d\n", errno);
-		return;
+	memcpy(dst, src, len);
+	dst += len;
+	dst[0] = '\n';
+	dst[1] = '\0';
+
+	/* Print into buffer */
+
+	dst = &buf[0];
+	rem = sizeof(buf) - 1;
+
+	n = sniprintf(dst, rem, "%s: ", rtems_bsd_syslog_priorities[pri]);
+	if (n <= rem) {
+		dst += (size_t) n;
+		rem -= (size_t) n;
 	}
 
-	/*
-	 * Create the mutex
-	 */
-	sc = rtems_semaphore_create (rtems_build_name('s', 'L', 'o', 'g'),
-					1,
-					RTEMS_PRIORITY |
-						RTEMS_BINARY_SEMAPHORE |
-						RTEMS_INHERIT_PRIORITY |
-						RTEMS_NO_PRIORITY_CEILING |
-						RTEMS_LOCAL,
-					0,
-					&LogSemaphore);
-	if (sc != RTEMS_SUCCESSFUL) {
-		printf ("Can't create syslog semaphore: %d\n", sc);
-		close (LogFd);
-		LogFd = -1;
+	n = sniprintf(dst, rem, "%s: ", rtems_bsd_program_get_name());
+	if (n <= rem) {
+		dst += (size_t) n;
+		rem -= (size_t) n;
 	}
+
+	vsniprintf(dst, rem, &fmt[0], ap);
+
+	/* Write in one rush */
+
+	fputs(&buf[0], stderr);
+}
+
+void
+openlog(const char *ident, int option, int facility)
+{
+	/* TODO */
 }
 
 void
 closelog(void)
 {
-	if (LogFd >= 0) {
-		close (LogFd);
-		LogFd = -1;
-		rtems_semaphore_delete (LogSemaphore);
-	}
+	/* TODO */
 }
 
 int
-setlogmask (int pmask)
+setlogmask(int mask)
 {
-	int omask;
+	rtems_bsd_syslog_context *ctx = rtems_bsd_syslog_get_context();
+	int cur = ctx->mask;
+
+	ctx->mask = mask & LOG_UPTO(LOG_DEBUG);
 
-	omask = LogMask;
-	if (pmask != 0)
-		LogMask = pmask;
-	return (omask);
+	return cur;
 }
diff --git a/testsuite/syscalls01/test_main.c b/testsuite/syscalls01/test_main.c
index 3f33e2b..75691d3 100644
--- a/testsuite/syscalls01/test_main.c
+++ b/testsuite/syscalls01/test_main.c
@@ -50,6 +50,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <syslog.h>
 
 #define RTEMS_BSD_PROGRAM_NO_EXIT_WRAP
 #define RTEMS_BSD_PROGRAM_NO_PRINTF_WRAP
@@ -1692,6 +1693,28 @@ test_err(void)
 }
 
 static void
+test_syslog(void)
+{
+	puts("test syslog");
+
+	errno = 0;
+	syslog(LOG_ERR, "%m");
+	syslog(LOG_ERR, "b%m");
+	syslog(LOG_ERR, "%me");
+	errno = ENXIO;
+	syslog(LOG_ERR, "<%m><%m><%m>");
+	syslog(LOG_INFO, "%m%m%m%m%m%m%m%m%m%m%m%m%m%m");
+	syslog(LOG_EMERG, "emerg");
+	syslog(LOG_ALERT, "alert");
+	syslog(LOG_CRIT, "crit");
+	syslog(LOG_ERR, "err");
+	syslog(LOG_WARNING, "warning");
+	syslog(LOG_NOTICE, "notice");
+	syslog(LOG_INFO, "info");
+	syslog(LOG_DEBUG, "debug");
+}
+
+static void
 test_main(void)
 {
 	/* Must be first test to ensure resource checks work */
@@ -1720,6 +1743,7 @@ test_main(void)
 	test_bsd_program();
 	test_warn();
 	test_err();
+	test_syslog();
 
 	exit(0);
 }



More information about the vc mailing list