Author: robert Date: 2008-01-18 14:13:49 -0700 (Fri, 18 Jan 2008) New Revision: 1896
Added: trunk/sysklogd/sysklogd-1.5-priv_sep-1.patch Log: Added sysklogd-1.5-priv_sep-1.patch Added: trunk/sysklogd/sysklogd-1.5-priv_sep-1.patch =================================================================== --- trunk/sysklogd/sysklogd-1.5-priv_sep-1.patch (rev 0) +++ trunk/sysklogd/sysklogd-1.5-priv_sep-1.patch 2008-01-18 21:13:49 UTC (rev 1896) @@ -0,0 +1,445 @@ +Submitted By: Robert Connolly <robert at linuxfromscratch dot org> (ashes) +Date: 2008-01-18 +Initial Package Version: 1.5 +Upstream Status: Submitted - Partially.. the Owl patches were submitted + http://www.infodrom.org/projects/sysklogd/download/patches/ +Origin: http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/sysklogd/ + sysklogd-1.4.2-caen-owl-klogd-drop-root.diff v1.2 + sysklogd-1.4.2-caen-owl-syslogd-drop-root.diff v1.1 + sysklogd-1.4.2-alt-syslogd-chroot.diff v1.2 + and the '-P' option from sysklogd_1.4.1-16ubuntu6.diff +Description: This patch adds the '-j' option to syslogd and klogd, so they +can chroot into a jail. This patch also adds the '-u' option to syslogd and +klogd, so they can change to the specified username before entering the jail. +This patch also adds '-P' to klogd so it can use an alternative /proc/kmsg +file, which is nescessary with Linux-2.6 and also works with Linux-2.4. + +To get klogd to drop privileges and work with Linux-2.6, root must make a +second copy of /proc/kmsg because the kernel checks for the CAP_SYS_ADMIN +capability before every read to /proc/kmsg. In Linux-2.4 the capability is +only checked when /proc/kmsg is first opened. + +Set up syslogd and klogd as regular users in a chroot jail like this: + +groupadd syslogd +groupadd klogd +useradd -d /var/lib/syslogd -s /bin/false -g syslogd syslogd +useradd -d /var/lib/klogd -s /bin/false -g klogd klogd + +install -d -m0000 /var/lib/syslogd +install -d -m0000 /var/lib/klogd + +This is a snippet of my /etc/rc.d/init.d/sysklogd file: + + start) + boot_mesg "Starting system log daemon..." + loadproc /usr/sbin/syslogd -m 0 -u syslogd -j /var/lib/syslogd + + boot_mesg "Starting kernel log daemon..." + /usr/bin/install -d -m0700 -o root -g root /var/run/klogd + /usr/bin/mkfifo -m 700 /var/run/klogd/kmsg + /bin/chown klogd:klogd /var/run/klogd/kmsg + /bin/sh -c -- '/bin/dd bs=1 if=/proc/kmsg of=/var/run/klogd/kmsg &' + loadproc /usr/sbin/klogd -x -u klogd -j /var/lib/klogd \ + -P /var/run/klogd/kmsg + ;; + + stop) + boot_mesg "Stopping kernel log daemon..." + killproc /usr/sbin/klogd + /bin/fuser -s -k /var/run/klogd/kmsg + /bin/rm -f /var/run/klogd/kmsg + + boot_mesg "Stopping system log daemon..." + killproc /usr/sbin/syslogd + ;; + +Remove the 'reload)' function, it will not work correctly after the daemons +have dropped to regular users. For the same reason, do not use 'kill -HUP' +with syslogd or klogd. + +The klogd daemon does not need to ever be root, but root privileges are +needed to chroot the klogd daemon. If you prefer klogd can be started with +'/bin/su', or the 'runas' program: +http://www.ibiblio.org/pub/Linux/system/security/runas-1.01.tar.gz +Also make sure the klogd user is able to read and execute /usr/sbin/klogd. + +diff -Naur sysklogd-1.5.orig/klogd.8 sysklogd-1.5.priv_sep/klogd.8 +--- sysklogd-1.5.orig/klogd.8 2007-05-28 17:25:43.000000000 +0000 ++++ sysklogd-1.5.priv_sep/klogd.8 2008-01-18 02:46:52.000000000 +0000 +@@ -14,10 +14,19 @@ + .RB [ " \-f " + .I fname + ] ++.RB [ " \-u " ++.I username ++] ++.RB [ " \-j " ++.I chroot_dir ++] + .RB [ " \-iI " ] + .RB [ " \-n " ] + .RB [ " \-o " ] + .RB [ " \-p " ] ++.RB [ " \-P " ++.I named_pipe ++] + .RB [ " \-s " ] + .RB [ " \-k " + .I fname +@@ -41,6 +50,20 @@ + .BI "\-f " file + Log messages to the specified filename rather than to the syslog facility. + .TP ++.BI "\-u " username ++Tells klogd to become the specified user and drop root privileges before ++starting logging. ++.TP ++.BI "\-j " chroot_dir ++Tells klogd to ++.BR chroot (2) ++into this directory after initializing. ++This option is only valid if the \-u option is also used to run klogd ++without root privileges. ++Note that the use of this option will prevent \-i and \-I from working ++unless you set up the chroot directory in such a way that klogd can still ++read the kernel module symbols. ++.TP + .BI "\-i \-I" + Signal the currently executing klogd daemon. Both of these switches control + the loading/reloading of symbol information. The \-i switch signals the +@@ -64,6 +87,13 @@ + symbol information whenever an Oops string is detected in the kernel message + stream. + .TP ++.B "-P" ++Read kernel messages from an alternative location, instead of from ++.IR /proc/kmsg . ++If \- is the argument then messages will be read from \fBstdin\fP, otherwise ++the argument must be the path of a FIFO named pipe created with ++.BR mkfifo (1) . ++.TP + .B "\-s" + Force \fBklogd\fP to use the system call interface to the kernel message + buffers. +diff -Naur sysklogd-1.5.orig/klogd.c sysklogd-1.5.priv_sep/klogd.c +--- sysklogd-1.5.orig/klogd.c 2007-06-17 19:21:55.000000000 +0000 ++++ sysklogd-1.5.priv_sep/klogd.c 2008-01-18 02:42:43.000000000 +0000 +@@ -268,6 +268,8 @@ + #include <stdarg.h> + #include <paths.h> + #include <stdlib.h> ++#include <pwd.h> ++#include <grp.h> + #include "klogd.h" + #include "ksyms.h" + #ifndef TESTING +@@ -313,11 +315,16 @@ + + 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; + int symbols_twice = 0; + ++char *server_user = NULL; ++char *chroot_dir = NULL; ++int log_flags = 0; + + /* Function prototypes. */ + extern int ksyslog(int type, char *buf, int len); +@@ -543,12 +550,29 @@ + "console output."); + } + ++ /* 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. + */ +- if ( use_syscall || +- ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) ++ if (!server_user && ++ (use_syscall || ++ ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)))) + { + /* Initialize kernel logging. */ + ksyslog(1, NULL, 0); +@@ -972,6 +996,27 @@ + } + + ++static int drop_root(void) ++{ ++ struct passwd *pw; ++ ++ if (!(pw = getpwnam(server_user))) return -1; ++ ++ if (!pw->pw_uid) return -1; ++ ++ if (chroot_dir) { ++ if (chdir(chroot_dir)) return -1; ++ if (chroot(".")) return -1; ++ } ++ ++ if (setgroups(0, NULL)) return -1; ++ if (setgid(pw->pw_gid)) return -1; ++ if (setuid(pw->pw_uid)) return -1; ++ ++ return 0; ++} ++ ++ + int main(argc, argv) + + int argc; +@@ -990,7 +1035,7 @@ + chdir ("/"); + #endif + /* Parse the command-line. */ +- while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF) ++ while ((ch = getopt(argc, argv, "c:df:u:j:iIk:nopP:svx2")) != EOF) + switch((char)ch) + { + case '2': /* Print lines with symbols twice. */ +@@ -1012,6 +1057,10 @@ + case 'I': + SignalDaemon(SIGUSR2); + return(0); ++ case 'j': /* chroot 'j'ail */ ++ chroot_dir = optarg; ++ log_flags |= LOG_NDELAY; ++ break; + case 'k': /* Kernel symbol file. */ + symfile = optarg; + break; +@@ -1024,9 +1073,15 @@ + 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; ++ case 'u': /* Run as this user */ ++ server_user = optarg; ++ break; + case 'v': + printf("klogd %s.%s\n", VERSION, PATCHLEVEL); + exit (1); +@@ -1035,6 +1090,10 @@ + break; + } + ++ if (chroot_dir && !server_user) { ++ fputs("'-j' is only valid with '-u'\n", stderr); ++ exit(1); ++ } + + /* Set console logging level. */ + if ( log_level != (char *) 0 ) +@@ -1144,7 +1203,7 @@ + } + } + else +- openlog("kernel", 0, LOG_KERN); ++ openlog("kernel", log_flags, LOG_KERN); + + + /* Handle one-shot logging. */ +@@ -1176,6 +1235,11 @@ + kill (ppid, SIGTERM); + #endif + ++ if (server_user && drop_root()) { ++ syslog(LOG_ALERT, "klogd: failed to drop root"); ++ Terminate(); ++ } ++ + /* The main loop. */ + while (1) + { +diff -Naur sysklogd-1.5.orig/sysklogd.8 sysklogd-1.5.priv_sep/sysklogd.8 +--- sysklogd-1.5.orig/sysklogd.8 2007-05-27 12:16:17.000000000 +0000 ++++ sysklogd-1.5.priv_sep/sysklogd.8 2008-01-18 02:42:43.000000000 +0000 +@@ -29,6 +29,12 @@ + .RB [ " \-s " + .I domainlist + ] ++.RB [ " \-u" ++.IB username ++] ++.RB [ " \-j " ++.I chroot_dir ++] + .RB [ " \-v " ] + .SH DESCRIPTION + .B Sysklogd +@@ -150,6 +156,32 @@ + no domain would be cut, you will have to specify two domains like: + .BR "\-s north.de:infodrom.north.de" . + .TP ++.BI "\-u " "username" ++This causes the ++.B syslogd ++daemon to become the named user before starting up logging. ++ ++Note that when this option is in use, ++.B syslogd ++will open all log files as root when the daemon is first started; ++however, after a ++.B SIGHUP ++the files will be reopened as the non-privileged user. You should ++take this into account when deciding the ownership of the log files. ++.TP ++.BI "\-j " chroot_dir ++Tells ++.B syslogd ++daemon to ++.BR chroot (2) ++into this directory after initializing. ++This option is only valid if the \-u option is also used to run ++.B syslogd ++without root privileges. ++Note that the use of this option will prevent ++.B SIGHUP ++from working which makes daemon reload practically impossible. ++.TP + .B "\-v" + Print version and exit. + .SH SIGNALS +diff -Naur sysklogd-1.5.orig/syslogd.c sysklogd-1.5.priv_sep/syslogd.c +--- sysklogd-1.5.orig/syslogd.c 2007-07-04 19:04:01.000000000 +0000 ++++ sysklogd-1.5.priv_sep/syslogd.c 2008-01-18 02:51:30.000000000 +0000 +@@ -538,6 +538,9 @@ + #include <sys/resource.h> + #include <signal.h> + ++#include <pwd.h> ++#include <grp.h> ++ + #include <netinet/in.h> + #include <netdb.h> + #include <syscall.h> +@@ -790,6 +793,9 @@ + int NoHops = 1; /* Can we bounce syslog messages through an + intermediate host. */ + ++char *server_user = NULL; /* user name to run server as */ ++char *chroot_dir = NULL; /* user name to run server as */ ++ + extern int errno; + + /* Function prototypes. */ +@@ -830,6 +836,26 @@ + static int create_inet_socket(); + #endif + ++static int drop_root(void) ++{ ++ struct passwd *pw; ++ ++ if (!(pw = getpwnam(server_user))) return -1; ++ ++ if (!pw->pw_uid) return -1; ++ ++ if (chroot_dir) { ++ if (chdir(chroot_dir)) return -1; ++ if (chroot(".")) return -1; ++ } ++ ++ if (initgroups(server_user, pw->pw_gid)) return -1; ++ if (setgid(pw->pw_gid)) return -1; ++ if (setuid(pw->pw_uid)) return -1; ++ ++ return 0; ++} ++ + int main(argc, argv) + int argc; + char **argv; +@@ -886,7 +912,7 @@ + funix[i] = -1; + } + +- while ((ch = getopt(argc, argv, "a:dhf:l:m:np:rs:v")) != EOF) ++ while ((ch = getopt(argc, argv, "a:dhf:j:l:m:np:rs:u:v")) != EOF) + switch((char)ch) { + case 'a': + if (nfunix < MAXFUNIX) +@@ -903,9 +929,12 @@ + case 'h': + NoHops = 0; + break; ++ case 'j': ++ chroot_dir = optarg; ++ break; + case 'l': + if (LocalHosts) { +- fprintf (stderr, "Only one -l argument allowed," \ ++ fprintf(stderr, "Only one -l argument allowed, " + "the first one is taken.\n"); + break; + } +@@ -931,6 +960,9 @@ + } + StripDomains = crunch_list(optarg); + break; ++ case 'u': ++ server_user = optarg; ++ break; + case 'v': + printf("syslogd %s.%s\n", VERSION, PATCHLEVEL); + exit (0); +@@ -941,6 +973,10 @@ + if ((argc -= optind)) + usage(); + ++ if (chroot_dir && !server_user) { ++ fputs("'-j' is only valid with '-u'\n", stderr); ++ exit(1); ++ } + #ifndef TESTING + if ( !(Debug || NoFork) ) + { +@@ -1087,6 +1123,11 @@ + kill (ppid, SIGTERM); + #endif + ++ if (server_user && drop_root()) { ++ dprintf("syslogd: failed to drop root\n"); ++ exit(1); ++ } ++ + /* Main loop begins here. */ + for (;;) { + int nfds; +@@ -1239,7 +1280,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] [-j chrootjail] [-u username]\n"); + exit(1); + } + -- http://linuxfromscratch.org/mailman/listinfo/patches FAQ: http://www.linuxfromscratch.org/faq/ Unsubscribe: See the above information page
