http://cvsweb.openwall.com/cgi/cvsweb.cgi/~checkout~/Owl/packages/sysklogd/sysklogd-1.4.2-caen-owl-klogd-drop-root.diff?rev=1.2;content-type=text%2Fplain
diff -upk.orig sysklogd-1.4.2.orig/klogd.8 sysklogd-1.4.2/klogd.8
--- sysklogd-1.4.2.orig/klogd.8 2005-03-11 16:12:09 +0000
+++ sysklogd-1.4.2/klogd.8 2005-08-18 14:37:47 +0000
@@ -18,6 +19,12 @@ klogd \- Kernel Log Daemon
.RB [ " \-f "
.I fname
]
+.RB [ " \-u "
+.I username
+]
+.RB [ " \-j "
+.I chroot_dir
+]
.RB [ " \-iI " ]
.RB [ " \-n " ]
.RB [ " \-o " ]
@@ -53,6 +60,20 @@ stderr.
.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
diff -upk.orig sysklogd-1.4.2.orig/klogd.c sysklogd-1.4.2/klogd.c
--- sysklogd-1.4.2.orig/klogd.c 2005-08-18 12:29:52 +0000
+++ sysklogd-1.4.2/klogd.c 2005-08-18 14:37:47 +0000
@@ -261,6 +261,8 @@
#include <stdarg.h>
#include <paths.h>
#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
#include "klogd.h"
#include "ksyms.h"
#ifndef TESTING
@@ -315,6 +317,9 @@ static enum LOGSRC {none, proc, kernel}
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);
@@ -535,8 +540,9 @@ static enum LOGSRC GetKernelLogSrc(void)
* 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);
@@ -983,6 +989,27 @@ static void LogProcLine(void)
}
+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;
@@ -1000,7 +1027,7 @@ int main(argc, argv)
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:nopsvx2")) != EOF)
switch((char)ch)
{
case '2': /* Print lines with symbols twice. */
@@ -1022,6 +1049,10 @@ int main(argc, argv)
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;
@@ -1037,6 +1068,9 @@ int main(argc, argv)
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);
@@ -1045,6 +1079,10 @@ int main(argc, argv)
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 )
@@ -1158,7 +1196,7 @@ int main(argc, argv)
}
}
else
- openlog("kernel", 0, LOG_KERN);
+ openlog("kernel", log_flags, LOG_KERN);
/* Handle one-shot logging. */
@@ -1191,6 +1229,11 @@ int main(argc, argv)
}
}
+ if (server_user && drop_root()) {
+ syslog(LOG_ALERT, "klogd: failed to drop root");
+ Terminate();
+ }
+
/* The main loop. */
while (1)
{