Submitted By: Jim Gifford (jim at linuxfromscratch dot org) Date: 2004-05-06 Initial Package Version: 1.4.1 Origin: Archaic Upstream Status: Unknown Description: Allows syslog and klog to use a specific user other than root diff -Nur sysklogd-1.4.1.orig/klogd.8 sysklogd-1.4.1/klogd.8 --- sysklogd-1.4.1.orig/klogd.8 Sun Mar 11 20:35:51 2001 +++ sysklogd-1.4.1/klogd.8 Fri Mar 16 14:11:38 2001 @@ -3,6 +3,7 @@ .\" Sun Jul 30 01:35:55 MET: Martin Schulze: Updates .\" Sun Nov 19 23:22:21 MET: Martin Schulze: Updates .\" Mon Aug 19 09:42:08 CDT 1996: Dr. G.W. Wettstein: Updates +.\" Thu Feb 17 2000: Chris Wing: Unprivileged klogd feature .\" .TH KLOGD 8 "21 August, 1999" "Version 1.4" "Linux System Administration" .SH NAME @@ -17,7 +18,11 @@ .RB [ " \-f " .I fname ] +.RB [ " \-u " +.I username +] .RB [ " \-iI " ] +.RB [ " \-r " ] .RB [ " \-n " ] .RB [ " \-o " ] .RB [ " \-p " ] @@ -46,11 +51,24 @@ .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. This is useful if you are paranoid about how well we wrote +this program. +.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 daemon to reload the kernel module symbols. The \-I switch signals for a reload of both the static kernel symbols and the kernel module symbols. +.TP +.B "\-r" +Reset kernel logging. You should run +.B klogd +with this argument after killing the daemon, if you run the daemon as a non- +privileged user. This is because +.B klogd +will be unable to reset kernel logging automatically in that case. .TP .B "\-n" Avoid auto-backgrounding. This is needed especially if the diff -Nur sysklogd-1.4.1.orig/klogd.c sysklogd-1.4.1/klogd.c --- sysklogd-1.4.1.orig/klogd.c Sun Mar 11 20:40:10 2001 +++ sysklogd-1.4.1/klogd.c Fri Mar 16 14:38:52 2001 @@ -275,6 +275,10 @@ #define ksyslog klogctl #endif +/* Support for running as an unprivileged user */ +#include +#include + #define LOG_BUFFER_SIZE 4096 #define LOG_LINE_LENGTH 1000 @@ -308,6 +312,9 @@ int debugging = 0; int symbols_twice = 0; +int drop_privileges = 0; +uid_t server_uid = 0; +gid_t server_gid = 0; /* Function prototypes. */ extern int ksyslog(int type, char *buf, int len); @@ -994,7 +1001,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:iIk:noprsvx2")) != EOF) switch((char)ch) { case '2': /* Print lines with symbols twice. */ @@ -1010,6 +1017,31 @@ output = optarg; use_output++; break; + case 'u': /* Run as this user */ + if (optarg) { + struct passwd *pwd; + + pwd = getpwnam(optarg); + if (!pwd) { + fprintf(stderr, "Failed to look up user %s " \ + "to switch to. Terminating.\n", optarg); + exit(1); + } + + drop_privileges = 1; + server_uid = pwd->pw_uid; + server_gid = pwd->pw_gid; + } else { + fprintf(stderr, "Must specify user name along " \ + "with -u option.\n"); + exit(1); + } + break; + case 'r': /* Reset logging */ + Syslog(LOG_INFO, "Resetting kernel logging."); + CloseLogSrc(); + exit(0); + break; case 'i': /* Reload module symbols. */ SignalDaemon(SIGUSR1); return(0); @@ -1161,6 +1193,13 @@ if (symbol_lookup) { InitKsyms(symfile); InitMsyms(); + } + + /* Drop privileges if a user name was specified on the command line */ + if (drop_privileges) { + setgroups(0, NULL); + setgid(server_gid); + setuid(server_uid); } /* The main loop. */ diff -Nur sysklogd-1.4.1.orig/sysklogd.8 sysklogd-1.4.1/sysklogd.8 --- sysklogd-1.4.1.orig/sysklogd.8 Sun Mar 11 20:35:51 2001 +++ sysklogd-1.4.1/sysklogd.8 Fri Mar 16 14:40:16 2001 @@ -29,6 +29,9 @@ .RB [ " \-s " .I domainlist ] +.RB [ " \-u" +.IB username +] .RB [ " \-v " ] .LP .SH DESCRIPTION @@ -149,6 +152,22 @@ is specified and the host logging resolves to satu.infodrom.north.de 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. This +option is useful if you are paranoid about how well we wrote this +program. + +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 .B "\-v" Print version and exit. diff -Nur sysklogd-1.4.1.orig/syslogd.c sysklogd-1.4.1/syslogd.c --- sysklogd-1.4.1.orig/syslogd.c Sun Mar 11 20:40:10 2001 +++ sysklogd-1.4.1/syslogd.c Fri Mar 16 14:44:02 2001 @@ -500,6 +500,10 @@ #include #endif +/* Support for running syslogd as non-root user */ +#include +#include + #ifndef UTMP_FILE #ifdef UTMP_FILENAME #define UTMP_FILE UTMP_FILENAME @@ -735,6 +739,7 @@ char **LocalHosts = NULL; /* these hosts are logged with their hostname */ int NoHops = 1; /* Can we bounce syslog messages through an intermediate host. */ +char *server_user = NULL; /* user name to run server as, instead of root */ extern int errno; @@ -829,7 +834,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:u:v")) != EOF) switch((char)ch) { case 'a': if (nfunix < MAXFUNIX) @@ -874,6 +879,15 @@ } StripDomains = crunch_list(optarg); break; + case 'u': + if (optarg) + server_user = strdup(optarg); + else { + fprintf (stderr, "Must specify user name " \ + "along with -u option.\n"); + exit (1); + } + break; case 'v': printf("syslogd %s.%s\n", VERSION, PATCHLEVEL); exit (0); @@ -1020,6 +1034,28 @@ if (getpid() != ppid) kill (ppid, SIGTERM); #endif + /* + * Drop privileges if a user name was specified on + * the command line. + */ + if (server_user) { + struct passwd *pwd; + + pwd = getpwnam(server_user); + if (!pwd) { + dprintf("Failed to look up user %s.\n", server_user); + exit(1); + } + + /* initgroups should not require the stupid "extra group" thingy */ + if (initgroups(server_user, pwd->pw_gid)) { + dprintf("Failed to set groups for user %s.\n", server_user); + exit(1); + } + + setgid(pwd->pw_gid); + setuid(pwd->pw_uid); + } /* Main loop begins here. */ for (;;) { @@ -1175,7 +1211,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 username]\n"); exit(1); }