Just attaching the original patch here in the BTS for reference, rather than
relying on the old link (which may go away soon).

-- 
 - mdz
diff -u sysklogd-1.4.1/syslogd.c sysklogd-1.4.1/syslogd.c
--- sysklogd-1.4.1/syslogd.c
+++ sysklogd-1.4.1/syslogd.c
@@ -46,6 +46,10 @@
  * extensive changes by Ralph Campbell
  * more extensive changes by Eric Allman (again)
  *
+ * Wed Nov 24 2004 14:02:48 CET 2004: Martin Pitt
+ *      Added option "-u <user>" to drop privileges to given user after
+ *      initialisation.
+ *
  * Steve Lord:	Fix UNIX domain socket code, added linux kernel logging
  *		change defines to
  *		SYSLOG_INET	- listen on a UDP socket
@@ -500,6 +504,9 @@
 #include <paths.h>
 #endif
 
+#include <pwd.h>
+#include <grp.h>
+
 #ifndef UTMP_FILE
 #ifdef UTMP_FILENAME
 #define UTMP_FILE UTMP_FILENAME
@@ -821,6 +828,11 @@
 	extern char *optarg;
 	int maxfds;
 
+        /* user and group id to drop to */
+        uid_t uid = 0;
+        gid_t gid = 0;
+        const char* username = NULL;
+
 #ifndef TESTING
 	chdir ("/");
 #endif
@@ -829,7 +841,7 @@
 		funix[i]  = -1;
 	}
 
-	while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:v")) != EOF)
+	while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:vu:")) != EOF)	
 		switch((char)ch) {
 		case 'a':
 			if (nfunix < MAXFUNIX)
@@ -877,6 +889,21 @@
 		case 'v':
 			printf("syslogd %s.%s\n", VERSION, PATCHLEVEL);
 			exit (0);
+		case 'u':
+                        if (optarg) {
+                                username = strdup (optarg);
+                                struct passwd *pw = getpwnam (username);
+                                if (!pw) {
+                                        fprintf (stderr, "User %s does not exist, aborting.\n", username);
+                                        exit (1);
+                                }
+                                uid = pw->pw_uid;
+                                gid = pw->pw_gid;
+                        } else {
+                                fputs ("Internal error: -u optarg == NULL!\n", stderr);
+                                exit (1);
+                        }
+			break;
 		case '?':
 		default:
 			usage();
@@ -1021,6 +1048,19 @@
 		kill (ppid, SIGTERM);
 #endif
 
+        /*
+         * Drop privileges if -u was specified
+         */
+	if (username) {
+                if (initgroups (username, gid) || 
+                    setgid (gid) || setuid (uid)) {
+                        perror ("Could not drop to specified user privileges");
+                        exit (1);
+                }
+                free (username);
+                username = NULL;
+        }
+
 	/* Main loop begins here. */
 	for (;;) {
 		int nfds;
@@ -1175,7 +1215,7 @@
 int usage()
 {
 	fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
-		" [-s domainlist] [-f conffile]\n");
+		" [-s domainlist] [-f conffile] [-u user]\n");
 	exit(1);
 }
 
diff -u sysklogd-1.4.1/debian/changelog sysklogd-1.4.1/debian/changelog
--- sysklogd-1.4.1/debian/changelog
+++ sysklogd-1.4.1/debian/changelog
@@ -1,3 +1,40 @@
+sysklogd (1.4.1-16.1) unstable; urgency=low
+
+  * Make syslogd and klogd run as normal user
+  * syslogd.c: support dropping root privileges to normal user
+    - added command line option "-u user"
+    - drop to specified user after opening the log files (so that the log
+      files can still be owned by root)
+    - added changelog entry
+  * sysklogd.8: document -u option
+  * debian/postinst, debian/postrm: create/remove user 'syslog'
+  * debian/rc: 
+    - use option "-u syslog" by default
+    - reloading using the SIGHUP signal does not work with root-owned log
+      files any more; completely restart the daemon instead
+  * debian/control: depend on adduser (for the rc script modifications)
+  * klogd.c:
+    - add option "-P file" to specify alternative kernel messages file
+      (instead of /proc/kmsg)
+    - added macro PIDFILE_DIR which is preferred over _PATH_VARRUN
+    - added changelog entry
+  * Makefile: added macro KLOGD_DEFINES for allowing to specify PIDFILE_DIR
+    (and other macros) without changing the Makefile
+  * debian/rules: compile klogd to use pidfile in /var/run/klogd
+  * postinst.klogd: 
+    - sleep a second after stopping the old klogd to avoid "klogd is already
+      running" failures on restart
+    - add/remove system user and group "klog"
+  * postrm.klogd: remove system user and group "klog" on purge
+  * debian/rc.klogd:
+    - create klogd pid file in /var/run/klogd/ (klog-writeable directory)
+    - create a klog-owned fifo /var/run/klogd/kmsg
+    - start/stop a dd process (running as root) which pipes /proc/kmsg to
+      /var/run/klogd/kmsg; this allows to run klogd entirely as user 'klogd'
+    - replaced restarting by calls to stop and start
+
+ -- Martin Pitt <martin.p...@canonical.com>  Wed, 24 Nov 2004 14:02:48 +0100
+
 sysklogd (1.4.1-16) unstable; urgency=medium
 
   * applied patch by cph
diff -u sysklogd-1.4.1/debian/control sysklogd-1.4.1/debian/control
--- sysklogd-1.4.1/debian/control
+++ sysklogd-1.4.1/debian/control
@@ -6,7 +6,7 @@
 
 Package: sysklogd
 Architecture: any
-Depends: ${shlibs:Depends}, klogd | linux-kernel-log-daemon
+Depends: ${shlibs:Depends}, klogd | linux-kernel-log-daemon, adduser
 Conflicts: syslogd
 Provides: syslogd, system-log-daemon
 Replaces: syslogd
@@ -18,7 +18,7 @@
 
 Package: klogd
 Architecture: any
-Depends: ${shlibs:Depends}, sysklogd | system-log-daemon
+Depends: ${shlibs:Depends}, sysklogd | system-log-daemon, adduser
 Conflicts: sysklogd (<= 1.3-33)
 Provides: linux-kernel-log-daemon
 Replaces: sysklogd
diff -u sysklogd-1.4.1/debian/postinst sysklogd-1.4.1/debian/postinst
--- sysklogd-1.4.1/debian/postinst
+++ sysklogd-1.4.1/debian/postinst
@@ -46,6 +46,8 @@
 
     update-rc.d sysklogd defaults 10 90 >/dev/null
 
+    adduser --system --group --no-create-home --quiet syslog
+
     # Create logfiles with correct file modes
     #
     for LOG in `syslogd-listfiles` `syslogd-listfiles --auth`
diff -u sysklogd-1.4.1/debian/postinst.klogd sysklogd-1.4.1/debian/postinst.klogd
--- sysklogd-1.4.1/debian/postinst.klogd
+++ sysklogd-1.4.1/debian/postinst.klogd
@@ -8,11 +8,14 @@
     then
 	set +e
 	sh /etc/init.d/klogd stop
+        sleep 1
 	set -e
     fi
 
     update-rc.d klogd defaults 11 89 >/dev/null
 
+    adduser --system --quiet --group --no-create-home klog || true
+
     # restarting daemon
     #
     if [ -f /etc/init.d/klogd ]
diff -u sysklogd-1.4.1/debian/postrm sysklogd-1.4.1/debian/postrm
--- sysklogd-1.4.1/debian/postrm
+++ sysklogd-1.4.1/debian/postrm
@@ -5,4 +5,5 @@
 if [ "$1" = "purge" ]
 then
+    deluser --system --quiet syslog
     update-rc.d sysklogd remove >/dev/null
 fi
diff -u sysklogd-1.4.1/debian/postrm.klogd sysklogd-1.4.1/debian/postrm.klogd
--- sysklogd-1.4.1/debian/postrm.klogd
+++ sysklogd-1.4.1/debian/postrm.klogd
@@ -5,4 +5,5 @@
 if [ "$1" = "purge" ]
 then
+  deluser --system --quiet klog || true
   update-rc.d klogd remove >/dev/null
 fi
diff -u sysklogd-1.4.1/debian/rc sysklogd-1.4.1/debian/rc
--- sysklogd-1.4.1/debian/rc
+++ sysklogd-1.4.1/debian/rc
@@ -11,7 +11,7 @@
 # Options for start/restart the daemons
 #   For remote UDP logging use SYSLOGD="-r"
 #
-SYSLOGD=""
+SYSLOGD="-u syslog"
 
 create_xconsole()
 {
@@ -70,29 +70,13 @@
     start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile
     echo "."
     ;;
-  reload|force-reload)
-    echo -n "Reloading system log daemon: syslogd"
-    start-stop-daemon --stop --quiet --signal 1 --exec $binpath --pidfile $pidfile
-    echo "."
-    ;;
-  restart)
+  restart|force-reload|reload-or-restart|reload)
     echo -n "Restarting system log daemon: syslogd"
     start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile
     sleep 1
     start-stop-daemon --start --quiet --exec $binpath -- $SYSLOGD
     echo "."
     ;;
-  reload-or-restart)
-    if running
-    then
-	echo -n "Reloading system log daemon: syslogd"
-	start-stop-daemon --stop --quiet --signal 1 --exec $binpath --pidfile $pidfile
-    else
-	echo -n "Restarting system log daemon: syslogd"
-	start-stop-daemon --start --quiet --exec $binpath -- $SYSLOGD
-    fi
-    echo "."
-    ;;
   *)
     echo "Usage: /etc/init.d/sysklogd {start|stop|reload|restart|force-reload|reload-or-restart}"
     exit 1
diff -u sysklogd-1.4.1/debian/rc.klogd sysklogd-1.4.1/debian/rc.klogd
--- sysklogd-1.4.1/debian/rc.klogd
+++ sysklogd-1.4.1/debian/rc.klogd
@@ -3,14 +3,16 @@
 
 PATH=/bin:/usr/bin:/sbin:/usr/sbin
 
-pidfile=/var/run/klogd.pid
+pidfile=/var/run/klogd/klogd.pid
+kmsgpipe=/var/run/klogd/kmsg
+kmsgpidfile=/var/run/klogd/kmsgpipe.pid
 binpath=/sbin/klogd
 
 test -f $binpath || exit 0
 
 #  Use KLOGD="-k /boot/System.map-$(uname -r)" to specify System.map
 #
-KLOGD=""
+KLOGD="-P $kmsgpipe"
 
 running()
 {
@@ -50,19 +52,34 @@
 case "$1" in
   start)
     echo -n "Starting kernel log daemon: klogd"
-    start-stop-daemon --start --quiet --exec $binpath -- $KLOGD
+
+    # create klog-writeable pid and fifo directory
+    mkdir -p /var/run/klogd
+    chown klog:klog /var/run/klogd
+    mkfifo -m 600 $kmsgpipe
+    chown klog:klog $kmsgpipe
+
+    # shovel /proc/kmsg to pipe readable by klogd user
+    start-stop-daemon --start --pidfile $kmsgpidfile --exec /bin/dd -b -m -- if=/proc/kmsg of=$kmsgpipe
+
+    # start klogd as non-root with reading from kmsgpipe
+    start-stop-daemon --start --quiet --chuid klog --exec $binpath -- $KLOGD
     echo "."
     ;;
   stop)
     echo -n "Stopping kernel log daemon: klogd"
     start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile
+
+    # stop kmsgpipe
+    start-stop-daemon --stop --quiet --oknodo --pidfile $kmsgpidfile
+    rm -f $kmsgpidfile $kmsgpipe
+
     echo "."
     ;;
   restart|force-reload)
-    echo -n "Restarting kernel log daemon: klogd"
-    start-stop-daemon --stop --quiet --exec $binpath --pidfile $pidfile
+    $0 stop
     sleep 1
-    start-stop-daemon --start --quiet --exec $binpath -- $KLOGD
+    $0 start
     echo "."
     ;;
   *)
diff -u sysklogd-1.4.1/debian/rules sysklogd-1.4.1/debian/rules
--- sysklogd-1.4.1/debian/rules
+++ sysklogd-1.4.1/debian/rules
@@ -39,7 +39,7 @@
 build:
 	$(MAKE) DEB="-DDEBRELEASE=\\\"$(revision)\\\"" \
 		CFLAGS="$(CFLAGS) -DSYSV -fomit-frame-pointer -fno-strength-reduce" \
-		LDFLAGS=""
+		LDFLAGS="" KLOGD_DEFINES='-DPIDFILE_DIR=\"/var/run/klogd/\"'
 	pod2man --section=8 --lax --center="Debian GNU/Linux" \
 	  --release="Debian Project" debian/syslog-facility.pod \
 	  > syslog-facility.8
only in patch2:
unchanged:
--- sysklogd-1.4.1.orig/Makefile
+++ sysklogd-1.4.1/Makefile
@@ -47,7 +47,7 @@
 SYSLOGD_FLAGS= -DSYSLOG_INET -DSYSLOG_UNIXAF -DNO_SCCS ${FSSTND} \
 	${SYSLOGD_PIDNAME}
 SYSLOG_FLAGS= -DALLOW_KERNEL_LOGGING
-KLOGD_FLAGS = ${FSSTND} ${KLOGD_START_DELAY}
+KLOGD_FLAGS = ${FSSTND} ${KLOGD_START_DELAY} ${KLOGD_DEFINES}
 DEB =
 
 .c.o:
only in patch2:
unchanged:
--- sysklogd-1.4.1.orig/sysklogd.8
+++ sysklogd-1.4.1/sysklogd.8
@@ -29,6 +29,9 @@
 .RB [ " \-s "
 .I domainlist
 ]
+.RB [ " \-u"
+.IB user
+]
 .RB [ " \-v " ]
 .LP
 .SH DESCRIPTION
@@ -150,6 +153,26 @@
 no domain would be cut, you will have to specify two domains like:
 .BR "\-s north.de:infodrom.north.de" .
 .TP
+.BI "\-u" " user"
+The
+.B syslogd
+daemon runs with full root privileges by default. If you specify this
+option, the daemon will drop its privileges to the given user (and the
+primary group of this user) before starting up logging. This
+greatly reduces the potential impact of exploitable security holes in
+syslogd.
+
+.B syslogd
+will still open all log files as root at startup.
+However, after receiving a
+.B SIGHUP
+signal (which causes the daemon to restart) the log files will be
+reopened as the non-privileged user which fails if the log files are
+only writeable by root. If you need to restart the daemon using the
+signal, then you have to adapt the permissions of your log files to be
+writeable by the specified user (or its primary group).
+
+.TP
 .B "\-v"
 Print version and exit.
 .LP
only in patch2:
unchanged:
--- sysklogd-1.4.1.orig/klogd.c
+++ sysklogd-1.4.1/klogd.c
@@ -20,6 +20,13 @@
 */
 
 /*
+ * Thu Nov 25 16:48:39 CET 2004:  Martin Pitt
+ *      Added option -P to give alternative location of /proc/kmsg ("-" for
+ *      stdin). This allows to run klogd entirely without root privileges.
+ *
+ *      Added support for macro PIDFILE_DIR which is used as pid file directory
+ *      instead of _PATH_VARRUN.
+ *
  * Steve Lord (l...@cray.com) 7th Nov 92
  *
  * Modified to check for kernel info by Dr. G.W. Wettstein 02/17/93.
@@ -279,7 +286,9 @@
 #define LOG_LINE_LENGTH 1000
 
 #ifndef TESTING
-#if defined(FSSTND)
+#if defined(PIDFILE_DIR)
+static char	*PidFile = PIDFILE_DIR "klogd.pid";
+#elif defined(FSSTND)
 static char	*PidFile = _PATH_VARRUN "klogd.pid";
 #else
 static char	*PidFile = "/etc/klogd.pid";
@@ -303,6 +312,8 @@
 
 static FILE *output_file = (FILE *) 0;
 
+static char     *kmsg_file = NULL; /* NULL means default /proc/kmsg */
+
 static enum LOGSRC {none, proc, kernel} logsrc;
 
 int debugging = 0;
@@ -524,6 +535,22 @@
 		ksyslog(6, NULL, 0);
 	}
 
+        /* Do we read kernel messages from a pipe? */
+        if ( kmsg_file ) {
+                if ( !strcmp(kmsg_file, "-") )
+                        kmsg = fileno(stdin);
+                else {
+                        if ( (kmsg = open(kmsg_file, O_RDONLY)) < 0 )
+                        {
+                                fprintf(stderr, "klogd: Cannot open kmsg file, " \
+                                        "%d - %s.\n", errno, strerror(errno));
+                                ksyslog(7, NULL, 0);
+                                exit(1);
+                        }
+                }
+                return proc;
+        }
+
 	/*
 	 * First do a stat to determine whether or not the proc based
 	 * file system is available to get kernel messages from.
@@ -994,7 +1021,7 @@
 	chdir ("/");
 #endif
 	/* Parse the command-line. */
-	while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF)
+	while ((ch = getopt(argc, argv, "c:df:iIk:nopP:svx2")) != EOF)
 		switch((char)ch)
 		{
 		    case '2':		/* Print lines with symbols twice. */
@@ -1028,6 +1055,9 @@
 		    case 'p':
 			SetParanoiaLevel(1);	/* Load symbols on oops. */
 			break;	
+                    case 'P':           /* Alternative kmsg file path */
+                        kmsg_file = strdup(optarg);
+                        break;
 		    case 's':		/* Use syscall interface. */
 			use_syscall = 1;
 			break;
@@ -1039,7 +1069,6 @@
 			break;
 		}
 
-
 	/* Set console logging level. */
 	if ( log_level != (char *) 0 )
 	{

Reply via email to