static void linux_minprivs(void) { unsigned int caps; /*% * Drop all privileges except the ability to bind() to privileged * ports. * * It's important that we drop CAP_SYS_CHROOT. If we didn't, it * chroot() could be used to escape from the chrooted area. */ caps = 0; caps |= (1 << CAP_NET_BIND_SERVICE); /* * 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); }
static void linux_initialprivs(void) { unsigned int caps; /*% * We don't need most privileges, so we drop them right away. * Later on linux_minprivs() will be called, which will drop our * capabilities to the minimum needed to run the server. */ caps = 0; /* * We need to be able to bind() to privileged ports, notably port 53! */ caps |= (1 << CAP_NET_BIND_SERVICE); /* * We need chroot() initially too. */ caps |= (1 << CAP_SYS_CHROOT); #if defined(HAVE_SYS_PRCTL_H) || !defined(HAVE_LINUXTHREADS) /* * 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 /* * Since we call initgroups, we need this. */ caps |= (1 << CAP_SETGID); /* * Without this, we run into problems reading a configuration file * owned by a non-root user and non-world-readable on startup. */ caps |= (1 << CAP_DAC_READ_SEARCH); /* * 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); }
static void linux_minprivs (void) { cap_t caps; #ifdef HAVE_LIBCAP cap_t curcaps; cap_value_t capval; char strbuf[ISC_STRERRORSIZE]; int err; #endif INIT_CAP; /*% * Drop all privileges except the ability to bind() to privileged * ports. * * It's important that we drop CAP_SYS_CHROOT. If we didn't, it * chroot() could be used to escape from the chrooted area. */ SET_CAP (CAP_NET_BIND_SERVICE); /* * 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. */ SET_CAP (CAP_SYS_RESOURCE); linux_setcaps (caps); #ifdef HAVE_LIBCAP FREE_CAP; #endif }
static void linux_setcaps(cap_t caps) { #ifndef HAVE_LIBCAP struct __user_cap_header_struct caphead; struct __user_cap_data_struct cap; #endif char strbuf[ISC_STRERRORSIZE]; if ((getuid() != 0 && !non_root_caps) || non_root) return; #ifndef HAVE_LIBCAP memset(&caphead, 0, sizeof(caphead)); caphead.version = _LINUX_CAPABILITY_VERSION; caphead.pid = 0; memset(&cap, 0, sizeof(cap)); cap.effective = caps; cap.permitted = caps; cap.inheritable = 0; #endif #ifdef HAVE_LIBCAP if (cap_set_proc(caps) < 0) { #else if (syscall(SYS_capset, &caphead, &cap) < 0) { #endif isc__strerror(errno, strbuf, sizeof(strbuf)); ns_main_earlyfatal(SETCAPS_FUNC "failed: %s:" " please ensure that the capset kernel" " module is loaded. see insmod(8)", strbuf); } } #ifdef HAVE_LIBCAP #define SET_CAP(flag) \ do { \ capval = (flag); \ cap_flag_value_t curval; \ err = cap_get_flag(curcaps, capval, CAP_PERMITTED, &curval); \ if (err != -1 && curval) { \ err = cap_set_flag(caps, CAP_EFFECTIVE, 1, &capval, CAP_SET); \ if (err == -1) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \ } \ \ err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, CAP_SET); \ if (err == -1) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \ } \ } \ } while (0) #define INIT_CAP \ do { \ caps = cap_init(); \ if (caps == NULL) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_init failed: %s", strbuf); \ } \ curcaps = cap_get_proc(); \ if (curcaps == NULL) { \ isc__strerror(errno, strbuf, sizeof(strbuf)); \ ns_main_earlyfatal("cap_get_proc failed: %s", strbuf); \ } \ } while (0) #define FREE_CAP \ { \ cap_free(caps); \ cap_free(curcaps); \ } while (0) #else #define SET_CAP(flag) do { caps |= (1 << (flag)); } while (0) #define INIT_CAP do { caps = 0; } while (0) #endif /* HAVE_LIBCAP */ static void linux_initialprivs(void) { cap_t caps; #ifdef HAVE_LIBCAP cap_t curcaps; cap_value_t capval; char strbuf[ISC_STRERRORSIZE]; int err; #endif /*% * We don't need most privileges, so we drop them right away. * Later on linux_minprivs() will be called, which will drop our * capabilities to the minimum needed to run the server. */ INIT_CAP; /* * We need to be able to bind() to privileged ports, notably port 53! */ SET_CAP(CAP_NET_BIND_SERVICE); /* * We need chroot() initially too. */ SET_CAP(CAP_SYS_CHROOT); #if defined(HAVE_SYS_PRCTL_H) || !defined(HAVE_LINUXTHREADS) /* * 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. */ SET_CAP(CAP_SETUID); #endif /* * Since we call initgroups, we need this. */ SET_CAP(CAP_SETGID); /* * Without this, we run into problems reading a configuration file * owned by a non-root user and non-world-readable on startup. */ SET_CAP(CAP_DAC_READ_SEARCH); /* * 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. */ SET_CAP(CAP_SYS_RESOURCE); /* * We need to be able to set the ownership of the containing * directory of the pid file when we create it. */ SET_CAP(CAP_CHOWN); linux_setcaps(caps); #ifdef HAVE_LIBCAP FREE_CAP; #endif }