Debian Bug report logs - #24326
sysklogd: syslogd shouldn't run as root

version graph

Package: sysklogd; Maintainer for sysklogd is Martin Schulze <joey@debian.org>; Source for sysklogd is src:sysklogd.

Reported by: Topi Miettinen <tom@medialab.sonera.net>

Date: Tue, 7 Jul 1998 21:33:02 UTC

Severity: wishlist

Merged with 35325

Found in versions 1.3-26, 1.3-31

Reply or subscribe to this bug.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#24326; Package sysklogd. Full text and rfc822 format available.

Acknowledgement sent to Topi Miettinen <tom@medialab.sonera.net>:
New bug report received and forwarded. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: Topi Miettinen <tom@medialab.sonera.net>
To: submit@bugs.debian.org
Subject: sysklogd: syslogd shouldn't run as root
Date: Wed, 8 Jul 1998 00:18:29 +0300
Package: sysklogd
Version: 1.3-26
Severity: wishlist

Syslogd does not need superuser privileges except for startup. Klogd needs 
privileges to open /proc/kmsg, but in current kernels (2.0.34, 2.1.107)
non-root reading from the file descriptor fails. That should eventually
be fixed.

This patch implements a new flag, -u user which causes syslogd and klogd
to call setuid(user).

diff -ru ./klogd.c.orig ./klogd.c
--- ./klogd.c.orig	Sun Jun 28 23:22:48 1998
+++ ./klogd.c	Sun Jun 28 23:26:49 1998
@@ -216,6 +216,7 @@
 #include <stdarg.h>
 #include <paths.h>
 #include <stdlib.h>
+#include <pwd.h>
 #include "klogd.h"
 #include "ksyms.h"
 #include "pidfile.h"
@@ -240,7 +241,7 @@
 static char	*PidFile = "/etc/klogd.pid";
 #endif
 
-static int	kmsg,
+static int	kmsg = -1,
 		change_state = 0,
 		terminate = 0,
 		caught_TSTP = 0,
@@ -490,7 +491,7 @@
 		return(kernel);
 	}
 	
-	if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
+	if ( kmsg == -1 && (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
 	{
 		fprintf(stderr, "klogd: Cannot open proc file system, " \
 			"%d - %s.\n", errno, strerror(errno));
@@ -878,10 +879,13 @@
 
 	auto char	*log_level = (char *) 0,
 			*output = (char *) 0;
+	uid_t		uid = 0;
+	gid_t		gid;
+	struct passwd	*pw;
 
 	chdir ("/");
 	/* Parse the command-line. */
-	while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx")) != EOF)
+	while ((ch = getopt(argc, argv, "c:df:iIk:nopsu:vx")) != EOF)
 		switch((char)ch)
 		{
 		    case 'c':		/* Set console message level. */
@@ -915,6 +919,15 @@
 		    case 's':		/* Use syscall interface. */
 			use_syscall = 1;
 			break;
+		    case 'u':
+			pw = getpwnam(optarg);
+			if (!pw) {
+                                printf("Bad user name %s\n", optarg);
+                                break;
+                        }
+                        uid = pw->pw_uid;
+                        gid = pw->pw_gid;
+			break;
 		    case 'v':
 			printf("klogd %s-%s\n", VERSION, PATCHLEVEL);
 			exit (1);
@@ -1044,6 +1057,11 @@
 	if (symbol_lookup) {
 		InitKsyms(symfile);
 		InitMsyms();
+	}
+
+	if (uid > 0) {
+		setgid(gid);
+		setuid(uid);
 	}
 
         /* The main loop. */
diff -ru ./syslogd.c.orig ./syslogd.c
--- ./syslogd.c.orig	Sun Jun 28 23:22:49 1998
+++ ./syslogd.c	Tue Jun 23 15:07:01 1998
@@ -400,6 +400,7 @@
 #include <arpa/nameser.h>
 #include <arpa/inet.h>
 #include <resolv.h>
+#include <pwd.h>
 #include "pidfile.h"
 #include "version.h"
 
@@ -700,9 +701,12 @@
 	char line[MAXLINE +1];
 	extern int optind;
 	extern char *optarg;
+	uid_t uid = 0;
+	gid_t gid;
+	struct passwd *pw;
 
 	chdir ("/");
-	while ((ch = getopt(argc, argv, "dhf:l:m:np:rs:v")) != EOF)
+	while ((ch = getopt(argc, argv, "dhf:l:m:np:rs:u:v")) != EOF)
 		switch((char)ch) {
 		case 'd':		/* debug */
 			Debug = 1;
@@ -741,6 +745,15 @@
 			}
 			StripDomains = crunch_list(optarg);
 			break;
+		case 'u':		/* user */
+			pw = getpwnam(optarg);
+			if (!pw) {
+				printf("Bad user name %s\n", optarg);
+				break;
+			}
+			uid = pw->pw_uid;
+			gid = pw->pw_gid;
+			break;
 		case 'v':
 			printf("syslogd %s-%s\n", VERSION, PATCHLEVEL);
 			exit (0);
@@ -865,6 +878,11 @@
 	{
 		dprintf("Debugging disabled, SIGUSR1 to turn on debugging.\n");
 		debugging_on = 0;
+	}
+
+	if (uid > 0) {
+		setgid(gid);
+		setuid(uid);
 	}
 
 	/* Main loop begins here. */


--- Begin /etc/init.d/sysklogd (modified conffile)
test -f /sbin/klogd || exit 0
test -f /sbin/syslogd || exit 0
SYSLOGD="-u syslogd"
KLOGD="-u syslogd"
case "$1" in
  start)
    echo -n "Starting system log daemon: syslogd"
    start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
    echo -n " klogd"
    start-stop-daemon --start --quiet --exec /sbin/klogd -- $KLOGD
    echo "."
    ;;
  stop)
    echo -n "Stopping system log daemon: klogd"
    start-stop-daemon --stop --quiet --pidfile /var/run/klogd.pid
    echo -n " syslogd"
    start-stop-daemon --stop --quiet --pidfile /var/run/syslogd.pid
    echo "."
    ;;
  reload|force-reload)
    start-stop-daemon --stop --quiet --signal 1 --pidfile /var/run/syslogd.pid
    ;;
  restart)
    echo -n "Stopping system log daemon: klogd"
    start-stop-daemon --stop --quiet --pidfile /var/run/klogd.pid
    echo " syslogd"
    start-stop-daemon --stop --quiet --pidfile /var/run/syslogd.pid
    sleep 1
    echo -n "Starting system log daemon: syslogd"
    start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
    echo -n " klogd"
    start-stop-daemon --start --quiet --exec /sbin/klogd -- $KLOGD
    echo "."
    ;;
  *)
    echo "Usage: /etc/init.d/sysklogd {start|stop|reload|restart|force-reload}"
    exit 1
esac
exit 0

--- End /etc/init.d/sysklogd

--- Begin /etc/cron.daily/sysklogd (modified conffile)
cd /var/log
for LOG in `syslogd-listfiles`
do
   if [ -f $LOG ]; then
      savelog -g adm -m 640 -u syslogd -c 7 $LOG >/dev/null
   fi
done
for LOG in `syslogd-listfiles --auth`
do
   if [ -f $LOG ]; then
      chown syslogd.adm $LOG
      chmod o-rwx $LOG
   fi
done
/etc/init.d/sysklogd reload

--- End /etc/cron.daily/sysklogd

--- Begin /etc/cron.weekly/sysklogd (modified conffile)
cd /var/log
for LOG in `syslogd-listfiles --weekly`
do
   if [ -f $LOG ]; then
      savelog -g adm -m 640 -u syslogd -c 4 $LOG >/dev/null
   fi
done
for LOG in `syslogd-listfiles --auth`
do
   if [ -f $LOG ]; then
      chown syslogd.adm $LOG
      chmod o-rwx $LOG
   fi
done
/etc/init.d/sysklogd reload

--- End /etc/cron.weekly/sysklogd


Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#24326; Package sysklogd. Full text and rfc822 format available.

Acknowledgement sent to Richard Kettlewell <rjk@greenend.org.uk>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #10 received at 24326@bugs.debian.org (full text, mbox):

From: Richard Kettlewell <rjk@greenend.org.uk>
To: 24326@bugs.debian.org
Subject: removing privilege from sysklogd
Date: Tue, 27 Oct 98 21:16:34 +0000 (GMT)
Just a quick observation about that patch - you must call initgroups()
before you call setuid(uid).

Otherwise sysklogd will still have all of root's additional groups in
its personality, which could give it privileged access that it ought
not to have.

This would represent a security hole (at least compared to the
intended behaviour - it would still be more secure than running as
root all the time!)

Additionally I notice that you've neglected to do any error checking
on the calls to setgid() and setuid().

ttfn/rjk


Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#24326; Package sysklogd. Full text and rfc822 format available.

Acknowledgement sent to Topi Miettinen <Topi.Miettinen@medialab.sonera.net>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #15 received at 24326@bugs.debian.org (full text, mbox):

From: Topi Miettinen <Topi.Miettinen@medialab.sonera.net>
To: 24326@bugs.debian.org
Subject: klogd -u patch update
Date: Sun, 22 Nov 1998 23:47:25 +0200
Good spotting. This new patch (for klogd only) calls setgroups, setgid and
setuid to change ids, checking return values.

BTW, at least in 2.1.129 /proc/kmsg should work as required.

syslogd needs more thought. The current patch does not work, as there are
several problems:
-restart (signal): reopening sockets will fail due to insufficient
privileges (may be circumvented with checking if the sockets are already
open, unless a config change requires a new privileged inet socket)
-cleanup at exit: removing unix sockets
-log file ownership

-Topi

diff -ru ./klogd.c.orig ./klogd.c
--- ./klogd.c.orig	Sun Nov 22 22:53:24 1998
+++ ./klogd.c	Sun Nov 22 22:55:48 1998
@@ -223,6 +223,8 @@
 #include <stdarg.h>
 #include <paths.h>
 #include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
 #include "klogd.h"
 #include "ksyms.h"
 #ifndef TESTING
@@ -251,7 +253,7 @@
 #endif
 #endif
 
-static int	kmsg,
+static int	kmsg = -1,
 		change_state = 0,
 		terminate = 0,
 		caught_TSTP = 0,
@@ -508,7 +510,7 @@
 	}
 
 #ifndef TESTING
-	if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
+	if (kmsg == -1 && (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0)
 	{
 		fprintf(stderr, "klogd: Cannot open proc file system, " \
 			"%d - %s.\n", errno, strerror(errno));
@@ -902,12 +904,15 @@
 
 	auto char	*log_level = (char *) 0,
 			*output = (char *) 0;
-
+	uid_t           uid = 0;
+	gid_t           gid = 0;
+	struct passwd   *pw;
+  
 #ifndef TESTING
 	chdir ("/");
 #endif
 	/* Parse the command-line. */
-	while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx")) != EOF)
+	while ((ch = getopt(argc, argv, "c:df:iIk:nopsu:vx")) != EOF)
 		switch((char)ch)
 		{
 		    case 'c':		/* Set console message level. */
@@ -941,6 +946,15 @@
 		    case 's':		/* Use syscall interface. */
 			use_syscall = 1;
 			break;
+		    case 'u':
+			pw = getpwnam(optarg);
+			if (!pw) {
+                                printf("Bad user name %s\n", optarg);
+                                break;
+                        }
+                        uid = pw->pw_uid;
+                        gid = pw->pw_gid;
+			break;
 		    case 'v':
 			printf("klogd %s-%s\n", VERSION, PATCHLEVEL);
 			exit (1);
@@ -1071,6 +1085,15 @@
 	if (symbol_lookup) {
 		InitKsyms(symfile);
 		InitMsyms();
+	}
+
+	if (uid > 0) {
+		if (setgroups(0, NULL) < 0 ||
+		    setgid(gid) < 0 ||
+		    setuid(uid) < 0) {
+			perror("error changing ids");
+			exit(1);
+		}
 	}
 
         /* The main loop. */





Information forwarded to debian-bugs-dist@lists.debian.org, Martin Schulze <joey@debian.org>:
Bug#24326; Package sysklogd. Full text and rfc822 format available.

Acknowledgement sent to Topi Miettinen <Topi.Miettinen@medialab.sonera.fi>:
Extra info received and forwarded to list. Copy sent to Martin Schulze <joey@debian.org>. Full text and rfc822 format available.

Message #20 received at 24326@bugs.debian.org (full text, mbox):

From: Topi Miettinen <Topi.Miettinen@medialab.sonera.fi>
To: 24326@bugs.debian.org
Subject: non-root syslogd
Date: Sun, 04 Apr 1999 23:53:36 +0300
It's better to start execution unprivileged rather than to switch uids later. 
This patch for syslogd allows changing pid file location, which was in the 
end the only problem with that approach. Restarting daemon and exit 
cleanup are no longer a problem.

This way requires that
- /dev/log is a symlink to a daemon-writable location (/var/run/syslogd/log)
- all current log files are writable by the daemon
- savelog scripts recreate log files with suitable ownership and 
permissions

Attached are the patch, /etc/cron.daily/sysklogd, and /etc/init.d/sysklogd.

Same approach could be attempted with klogd, using a new flag for specifying 
alternate /proc/kmsg file with '-' for stdin. Start with:
su - syslogd "klogd -P -" </proc/kmsg

-Topi

diff -ru ./syslogd.c.orig ./syslogd.c
--- ./syslogd.c.orig	Sat Jan 30 19:03:09 1999
+++ ./syslogd.c	Sun Apr  4 23:33:51 1999
@@ -797,7 +797,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:P:rs:v")) != EOF)
 		switch((char)ch) {
 		case 'a':
 			if (nfunix < MAXFUNIX)
@@ -830,6 +830,9 @@
 			break;
 		case 'p':		/* path to regular log socket */
 			funixn[0] = optarg;
+			break;
+		case 'P':		/* path to pid file*/
+			PidFile = optarg;
 			break;
 		case 'r':		/* accept remote messages */
 			AcceptRemote = 1;

#! /bin/sh

# sysklogd	Cron script to rotate system log files daily.
#
#		If you want to rotate other logfiles daily, edit
#		this script.  An easy way is to add them manually
#		or to add -a to syslogd-listfiles and add some grep
#		stuff
#
#		Written by Martin Schulze <joey@debian.org>.
#		$Id: cron.daily,v 1.2 1998/01/02 03:07:21 joey Exp $

cd /var/log
for LOG in `syslogd-listfiles`
do
   if [ -f $LOG ]; then
      savelog -g bin -m 640 -u bin -c 7 $LOG >/dev/null
   fi
done

for LOG in `syslogd-listfiles --all`
do
   if [ -f $LOG ]; then
      chown syslogd.syslogd $LOG
      chmod o-rwx $LOG
   fi
done

# Restart syslogd
#
/etc/init.d/sysklogd reload

#! /bin/sh
# /etc/init.d/sysklogd: start system and kernel log daemons.

test -f /sbin/klogd || exit 0
test -f /sbin/syslogd || exit 0

# Options for start/restart the daemons
#   For remote UDP logging use SYSLOGD="-r"
#
#SYSLOGD="-u syslogd"
SPID="/home/syslogd/syslogd.pid"
SYSLOGD="-p /home/syslogd/log -P $SPID"

#  Use KLOGD="-k /boot/System.map-$(uname -r)" to specify System.map
#
KLOGD="-u syslogd"
KPID="/var/run/klogd.pid"

case "$1" in
  start)
    echo -n "Starting system log daemon: syslogd"
    su - syslogd -c "/sbin/start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD"
    echo -n " klogd"
    start-stop-daemon --start --quiet --exec /sbin/klogd -- $KLOGD
    echo "."
    ;;
  stop)
    echo -n "Stopping system log daemon: klogd"
    start-stop-daemon --stop --quiet --pidfile $KPID
    echo -n " syslogd"
    start-stop-daemon --stop --quiet --pidfile $SPID
    echo "."
    ;;
  reload|force-reload)
    start-stop-daemon --stop --quiet --signal 1 --pidfile $SPID
    ;;
  restart)
    echo -n "Stopping system log daemon: klogd"
    start-stop-daemon --stop --quiet --pidfile $KPID
    echo " syslogd"
    start-stop-daemon --stop --quiet --pidfile $SPID
    sleep 1
    echo -n "Starting system log daemon: syslogd"
    su - syslogd -c "/sbin/start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD"
    echo -n " klogd"
    start-stop-daemon --start --quiet --exec /sbin/klogd -- $KLOGD
    echo "."
    ;;
  *)
    echo "Usage: /etc/init.d/sysklogd {start|stop|reload|restart|force-reload}"
    exit 1
esac

exit 0




Merged 24326 35325. Request was from Andreas Barth <aba@not.so.argh.org> to control@bugs.debian.org. Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Wed Feb 10 02:41:29 2010; Machine Name: busoni.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.