Dear all,

I have discovered a NULL pointer leading to segmentation fault.
The rescue has been verified on GNU/Linux and OpenBSD.

Alongside comes a first test script to check the abilites of the
syslogd server. The script was really intended for the upcoming
IPv6 changes, but proved instrumental in locating also the present
defect.

I am asking for acceptance as usual.

Best regards,
  Mats
From 95a10b4ce541ae945457ad06a9d4381fe075bded Mon Sep 17 00:00:00 2001
From: Mats Erik Andersson <[email protected]>
Date: Wed, 11 May 2011 12:56:03 +0200
Subject: [PATCH] syslogd: Dereferencing NULL error.

Permanent host lookup failures must lead to
a discarded forwarding request.  A new test
script includes the verification of this ability.
---
 ChangeLog         |    9 +++
 src/syslogd.c     |   15 ++++--
 tests/Makefile.am |    6 ++
 tests/syslogd.sh  |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 166 insertions(+), 4 deletions(-)
 create mode 100644 tests/syslogd.sh

diff --git a/ChangeLog b/ChangeLog
index 09cdd2c..458b064 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2011-05-11  Mats Erik Andersson <[email protected]>
+
+	* src/syslogd.d (fprintlog): Sanity check on `f->f_prevhost'
+	to avoid deferencing NULL.
+	(cfline): A permanently failed DNS lookup must produce F_UNUSED.
+	* tests/syslogd.sh: New file.
+	* tests/Makefile.am (dist_check_SCRIPTS) [ENABLE_logger &&
+	ENABLE_syslogd]: Add `syslogd.sh'.
+
 2011-05-09  Simon Josefsson  <[email protected]>
 
 	* bootstrap.conf (gnulib_modules): Removed 'exit' from list.
diff --git a/src/syslogd.c b/src/syslogd.c
index 5927f9f..0e94d84 100644
--- a/src/syslogd.c
+++ b/src/syslogd.c
@@ -1148,9 +1148,12 @@ fprintlog (struct filed *f, const char *from, int flags, const char *msg)
       v->iov_len = 1;
       v++;
     }
-  v->iov_base = f->f_prevhost;
-  v->iov_len = strlen (v->iov_base);
-  v++;
+  if (f->f_prevhost)
+    {
+      v->iov_base = f->f_prevhost;
+      v->iov_len = strlen (v->iov_base);
+      v++;
+    }
   v->iov_base = (char *) " ";
   v->iov_len = 1;
   v++;
@@ -1919,7 +1922,11 @@ cfline (const char *line, struct filed *f)
       hp = gethostbyname (p);
       if (hp == NULL)
 	{
-	  f->f_type = F_FORW_UNKN;
+	  extern int h_errno;
+	  if (h_errno == NO_DATA || h_errno == HOST_NOT_FOUND)
+	    f->f_type = F_UNUSED;	/* No recovery possible.  */
+	  else
+	    f->f_type = F_FORW_UNKN;	/* Temporary failure.  */
 	  f->f_prevcount = INET_RETRY_MAX;
 	  f->f_time = time ((time_t *) 0);
 	}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 846f24c..a70193d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,6 +40,12 @@ dist_check_SCRIPTS += tftp.sh
 endif
 endif
 endif
+if ENABLE_logger
+if ENABLE_syslogd
+dist_check_SCRIPTS += syslogd.sh
+endif
+endif
+
 TESTS = $(check_PROGRAMS) $(dist_check_SCRIPTS)
 
 TESTS_ENVIRONMENT = EXEEXT=$(EXEEXT)
diff --git a/tests/syslogd.sh b/tests/syslogd.sh
new file mode 100644
index 0000000..8b0cd88
--- /dev/null
+++ b/tests/syslogd.sh
@@ -0,0 +1,140 @@
+#!/bin/sh
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Inetutils.
+#
+# GNU Inetutils is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# GNU Inetutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see `http://www.gnu.org/licenses/'.
+
+# Tests to establish functionality of SYSLOG daemon.
+#
+
+# Keep any external assignment.
+#
+: ${IU_TESTDIR:=/tmp/iu_syslog}
+
+mkdir -p $IU_TESTDIR
+
+CONF=$IU_TESTDIR/syslog.conf
+PID=$IU_TESTDIR/syslogd.pid
+OUT=$IU_TESTDIR/messages
+: ${SOCKET:=$IU_TESTDIR/log}
+
+IU_SYSLOGD=./src/syslogd$EXEEXT
+IU_LOGGER=./src/logger$EXEEXT
+
+# All messages intended for post-detection are
+# to be uniformly tagged.
+TAG="syslogd-test"
+
+# Step out of `tests/', should the invokation
+# have been made there.
+#
+[ -d ../src ] && cd ..
+
+if [ ! -x $IU_SYSLOGD ]; then
+	echo "Missing executable 'syslogd'. Failing."
+	exit 1;
+fi
+
+if [ ! -x $IU_LOGGER ]; then
+	echo "Missing executable 'logger'. Failing."
+	exit 1
+fi
+
+# Remove old messages.
+rm -f $OUT $PID
+
+# Full testing needs a superuser.  Report this.
+if [ "$USER" != "root" ]; then
+	cat <<-EOT
+	WARNING!!
+	Disabling INET server tests since you seem
+	to be underprivileged.
+	EOT
+fi
+
+# A minimal, catch-all configuration.
+#
+cat > $CONF <<-EOT
+	*.*	$OUT
+	*.*	@not.in.existence
+EOT
+
+# Attempt to start the server after first
+# building the desired option list.
+#
+## Base configuration.
+IU_OPTIONS="--rcfile=$CONF --pidfile=$PID --socket=$SOCKET"
+## Enable INET service when running as root.
+if [ "$USER" = "root" ]; then
+	IU_OPTIONS="$IU_OPTIONS --inet"
+fi
+## Bring in additional options from command line.
+## Disable kernel messages otherwise.
+: OPTIONS=${OPTIONS:=--no-klog}
+IU_OPTIONS="$IU_OPTIONS $OPTIONS"
+
+$IU_SYSLOGD $IU_OPTIONS
+
+# Wait a moment in order to avoid an obvious
+# race condition with the server daemon on
+# slow systems.
+#
+sleep 1
+
+# Test to see whether the service got started.
+#
+if [ ! -r $PID ]; then
+	echo "The service daemon never started. Failing."
+	exit 1
+fi
+
+# Declare the number of implemented tests,
+# as well as an exit code.
+#
+TESTCASES=0
+EXITCODE=1
+
+# Send messages on two sockets: IPv4 and UNIX.
+#
+TESTCASES=$((TESTCASES + 1))
+$IU_LOGGER -h $SOCKET -p user -t $TAG "Sending BSD message."
+
+if [ "$USER" = "root" ]; then
+	TESTCASES=$((TESTCASES + 1))
+	$IU_LOGGER -4 -h localhost -p user -t $TAG "Sending IPv4 message."
+fi
+
+# Detection of registered messages.
+#
+TEXTLINES="$(grep $TAG $OUT | wc -l)"
+
+if [ -n "${VERBOSE+yes}" ]; then
+	grep $TAG $OUT
+fi
+
+echo "Registered $TEXTLINES lines out of $TESTCASES."
+
+if [ "$TEXTLINES" -eq "$TESTCASES" ]; then
+	echo "Successful testing."
+	EXITCODE=0
+else
+	echo "Failing some tests."
+fi
+
+# Remove the daemon process.
+[ -r $PID ] && kill "$(cat $PID)"
+
+exit $EXITCODE
-- 
1.7.4.4

Attachment: signature.asc
Description: Digital signature

Reply via email to