diff options
author | Internet Software Consortium, Inc <@isc.org> | 2007-09-07 14:08:38 -0600 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2007-09-07 14:08:38 -0600 |
commit | 1430f0bc941f5280d1359e99a8db3f8cddf028ef (patch) | |
tree | dfde1f88900db0e15b72a37fe3f34a9c308402ba /bin/named/unix/os.c | |
parent | 59cfa71487b8acf6ca955d054a2e6cbe7db482ac (diff) | |
download | bind9-1430f0bc941f5280d1359e99a8db3f8cddf028ef.tar.gz |
9.1.0b1
Diffstat (limited to 'bin/named/unix/os.c')
-rw-r--r-- | bin/named/unix/os.c | 138 |
1 files changed, 105 insertions, 33 deletions
diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index 7fee42c9..22ef56da 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -1,23 +1,24 @@ /* * Copyright (C) 1999, 2000 Internet Software Consortium. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.c,v 1.18.2.3 2000/08/15 00:20:57 gson Exp $ */ +/* $Id: os.c,v 1.35 2000/11/14 23:57:45 tale Exp $ */ #include <config.h> +#include <stdarg.h> #include <sys/stat.h> @@ -31,16 +32,61 @@ #include <syslog.h> #include <unistd.h> +#include <isc/print.h> +#include <isc/result.h> #include <isc/string.h> #include <named/main.h> #include <named/os.h> static char *pidfile = NULL; + +/* + * If there's no <linux/capability.h>, we don't care about <linux/prctl.h> + */ +#ifndef HAVE_LINUX_CAPABILITY_H +#undef HAVE_LINUX_PRCTL_H +#endif + +/* + * Linux defines: + * (T) HAVE_LINUXTHREADS + * (C) HAVE_LINUX_CAPABILITY_H + * (P) HAVE_LINUX_PRCTL_H + * The possible cases are: + * none: setuid() normally + * T: no setuid() + * C: setuid() normally, drop caps (keep CAP_SETUID) + * T+C: no setuid(), drop caps (don't keep CAP_SETUID) + * T+C+P: setuid() early, drop caps (keep CAP_SETUID) + * C+P: setuid() normally, drop caps (keep CAP_SETUID) + * P: not possible + * T+P: not possible + * + * if (C) + * caps = BIND_SERVICE + CHROOT + SETGID + * if ((T && C && P) || !T) + * caps += SETUID + * endif + * capset(caps) + * endif + * if (T && C && P && -u) + * setuid() + * else if (T && -u) + * fail + * --> start threads + * if (!T && -u) + * setuid() + * if (C && (P || !-u)) + * caps = BIND_SERVICE + * capset(caps) + * endif + * + * It will be nice when Linux threads work properly with setuid(). + */ + #ifdef HAVE_LINUXTHREADS static pid_t mainpid = 0; -static isc_boolean_t non_root_caps = ISC_FALSE; -static isc_boolean_t non_root = ISC_FALSE; #endif static struct passwd *runas_pw = NULL; @@ -48,6 +94,9 @@ static isc_boolean_t done_setuid = ISC_FALSE; #ifdef HAVE_LINUX_CAPABILITY_H +static isc_boolean_t non_root = ISC_FALSE; +static isc_boolean_t non_root_caps = ISC_FALSE; + /* * We define _LINUX_FS_H to prevent it from being included. We don't need * anything from it, and the files it includes cause warnings with 2.2 @@ -119,10 +168,12 @@ linux_initialprivs(void) { */ caps |= (1 << CAP_SYS_CHROOT); -#ifdef HAVE_LINUX_PRCTL_H +#if defined(HAVE_LINUX_PRCTL_H) || !defined(HAVE_LINUXTHREADS) /* - * If the kernel supports keeping capabilities after setuid(), we - * also want the setuid capability. We don't know until we've tried. + * We can setuid() only if either the kernel supports keeping + * capabilities after setuid() (which we don't know until we've + * tried) or we're not using threads. If either of these is + * true, we want the setuid capability. */ caps |= (1 << CAP_SETUID); #endif @@ -135,7 +186,11 @@ linux_initialprivs(void) { /* * XXX We might want to add CAP_SYS_RESOURCE, though it's not * clear it would work right given the way linuxthreads work. + * XXXDCL But since we need to be able to set the maximum number + * of files, the stack size, data size, and core dump size to + * support named.conf options, this is now being added to test. */ + caps |= (1 << CAP_SYS_RESOURCE); linux_setcaps(caps); } @@ -182,7 +237,7 @@ linux_keepcaps(void) { static void -setup_syslog(void) { +setup_syslog(const char *progname) { int options; options = LOG_PID; @@ -190,12 +245,12 @@ setup_syslog(void) { options |= LOG_NDELAY; #endif - openlog("named", options, LOG_DAEMON); + openlog(progname, options, LOG_DAEMON); } void -ns_os_init(void) { - setup_syslog(); +ns_os_init(const char *progname) { + setup_syslog(progname); #ifdef HAVE_LINUX_CAPABILITY_H linux_initialprivs(); #endif @@ -302,33 +357,43 @@ ns_os_changeuser(void) { done_setuid = ISC_TRUE; #ifdef HAVE_LINUXTHREADS +#ifdef HAVE_LINUX_CAPABILITY_H if (!non_root_caps) +#endif ns_main_earlyfatal( - "-u not supported on Linux kernels older than 2.3.99-pre3"); -#endif + "-u not supported on Linux kernels older than " + "2.3.99-pre3 when using threads"); +#endif if (setgid(runas_pw->pw_gid) < 0) ns_main_earlyfatal("setgid(): %s", strerror(errno)); if (setuid(runas_pw->pw_uid) < 0) ns_main_earlyfatal("setuid(): %s", strerror(errno)); + +#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS) + linux_minprivs(); +#endif } void ns_os_minprivs(void) { -#ifdef HAVE_LINUX_CAPABILITY_H #ifdef HAVE_LINUX_PRCTL_H linux_keepcaps(); - ns_os_changeuser(); #endif - linux_minprivs(); +#ifdef HAVE_LINUXTHREADS + ns_os_changeuser(); /* Call setuid() before threads are started */ +#endif -#endif /* HAVE_LINUX_CAPABILITY_H */ +#if defined(HAVE_LINUX_CAPABILITY_H) && defined(HAVE_LINUXTHREADS) + linux_minprivs(); +#endif } static int -safe_open(const char *filename) { +safe_open(const char *filename, isc_boolean_t append) { + int fd; struct stat sb; if (stat(filename, &sb) == -1) { @@ -337,16 +402,23 @@ safe_open(const char *filename) { } else if ((sb.st_mode & S_IFREG) == 0) return (-1); - (void)unlink(filename); - return (open(filename, O_WRONLY|O_CREAT|O_EXCL, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)); + if (append) + fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + else { + (void)unlink(filename); + fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + } + return (fd); } static void cleanup_pidfile(void) { - if (pidfile != NULL) + if (pidfile != NULL) { (void)unlink(pidfile); - free(pidfile); + free(pidfile); + } pidfile = NULL; } @@ -371,7 +443,7 @@ ns_os_writepidfile(const char *filename) { /* This is safe. */ strcpy(pidfile, filename); - fd = safe_open(filename); + fd = safe_open(filename, ISC_FALSE); if (fd < 0) ns_main_earlyfatal("couldn't open pid file '%s': %s", filename, strerror(errno)); |