diff --git a/CHANGES b/CHANGES index 862b8ac720..8e40250b07 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4986. [func] Linux capabilities now require libcap library. + [GL #321] + 4985. [func] Add a new slave zone option, "mirror", to enable serving a non-authoritative copy of a zone that is subject to DNSSEC validation before being diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index f48e74928a..717cb023c5 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -72,11 +72,13 @@ DEPLIBS = ${NSDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ LIBS = ${NSLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ - ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ + ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBCAP_LIBS@ \ + @LIBS@ NOSYMLIBS = ${NSLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ - ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ + ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBCAP_LIBS@ \ + @LIBS@ SUBDIRS = unix diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index 9448c5b997..48acbcef6a 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -59,16 +59,16 @@ static int singletonfd = -1; #endif /* - * If there's no , we don't care about + * If there's no , we don't care about */ -#ifndef HAVE_LINUX_CAPABILITY_H +#ifndef HAVE_SYS_CAPABILITY_H #undef HAVE_SYS_PRCTL_H #endif /* * Linux defines: * (T) HAVE_LINUXTHREADS - * (C) HAVE_SYS_CAPABILITY_H (or HAVE_LINUX_CAPABILITY_H) + * (C) HAVE_SYS_CAPABILITY_H * (P) HAVE_SYS_PRCTL_H * The possible cases are: * none: setuid() normally @@ -110,89 +110,33 @@ static struct passwd *runas_pw = NULL; static isc_boolean_t done_setuid = ISC_FALSE; static int dfd[2] = { -1, -1 }; -#ifdef HAVE_LINUX_CAPABILITY_H +#ifdef HAVE_SYS_CAPABILITY_H static isc_boolean_t non_root = ISC_FALSE; static isc_boolean_t non_root_caps = ISC_FALSE; -#ifdef HAVE_SYS_CAPABILITY_H #include -#else -#ifdef HAVE_LINUX_TYPES_H -#include -#endif -/*% - * 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 - * kernels, and compilation failures (due to conflicts between - * and ) on 2.3 kernels. - */ -#define _LINUX_FS_H -#include -#include -#ifndef SYS_capset -#ifndef __NR_capset -#include /* Slackware 4.0 needs this. */ -#endif /* __NR_capset */ -#define SYS_capset __NR_capset -#endif /* SYS_capset */ -#endif /* HAVE_SYS_CAPABILITY_H */ #ifdef HAVE_SYS_PRCTL_H #include /* Required for prctl(). */ - -/* - * If the value of PR_SET_KEEPCAPS is not in , define it - * here. This allows setuid() to work on systems running a new enough - * kernel but with /usr/include/linux pointing to "standard" kernel - * headers. - */ -#ifndef PR_SET_KEEPCAPS -#define PR_SET_KEEPCAPS 8 -#endif - #endif /* HAVE_SYS_PRCTL_H */ -#ifdef HAVE_LIBCAP -#define SETCAPS_FUNC "cap_set_proc " -#else -typedef unsigned int cap_t; -#define SETCAPS_FUNC "syscall(capset) " -#endif /* HAVE_LIBCAP */ - 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) + 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)); - named_main_earlyfatal(SETCAPS_FUNC "failed: %s:" + named_main_earlyfatal("cap_set_proc() failed: %s:" " please ensure that the capset kernel" " module is loaded. see insmod(8)", strbuf); } } -#ifdef HAVE_LIBCAP #define SET_CAP(flag) \ do { \ cap_flag_value_t curval; \ @@ -230,20 +174,14 @@ linux_setcaps(cap_t caps) { 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. @@ -300,20 +238,16 @@ linux_initialprivs(void) { linux_setcaps(caps); -#ifdef HAVE_LIBCAP FREE_CAP; -#endif } 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; /*% @@ -337,9 +271,7 @@ linux_minprivs(void) { linux_setcaps(caps); -#ifdef HAVE_LIBCAP FREE_CAP; -#endif } #ifdef HAVE_SYS_PRCTL_H @@ -364,7 +296,7 @@ linux_keepcaps(void) { } #endif -#endif /* HAVE_LINUX_CAPABILITY_H */ +#endif /* HAVE_SYS_CAPABILITY_H */ static void @@ -381,7 +313,7 @@ setup_syslog(const char *progname) { void named_os_init(const char *progname) { setup_syslog(progname); -#ifdef HAVE_LINUX_CAPABILITY_H +#ifdef HAVE_SYS_CAPABILITY_H linux_initialprivs(); #endif #ifdef HAVE_LINUXTHREADS @@ -567,11 +499,12 @@ named_os_changeuser(void) { done_setuid = ISC_TRUE; #ifdef HAVE_LINUXTHREADS -#ifdef HAVE_LINUX_CAPABILITY_H - if (!non_root_caps) +#ifdef HAVE_SYS_CAPABILITY_H + if (!non_root_caps) { named_main_earlyfatal("-u with Linux threads not supported: " "requires kernel support for " "prctl(PR_SET_KEEPCAPS)"); + } #else named_main_earlyfatal("-u with Linux threads not supported: " "no capabilities support or capabilities " @@ -600,7 +533,7 @@ named_os_changeuser(void) { strbuf); } #endif -#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS) +#if defined(HAVE_SYS_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS) linux_minprivs(); #endif } @@ -640,7 +573,7 @@ named_os_minprivs(void) { named_os_changeuser(); /* Call setuid() before threads are started */ #endif -#if defined(HAVE_LINUX_CAPABILITY_H) && defined(HAVE_LINUXTHREADS) +#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_LINUXTHREADS) linux_minprivs(); #endif } diff --git a/config.h.in b/config.h.in index 686352be1b..94f5aab4d0 100644 --- a/config.h.in +++ b/config.h.in @@ -317,9 +317,6 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the `c' library (-lc). */ #undef HAVE_LIBC -/* Define to 1 if you have the `cap' library (-lcap). */ -#undef HAVE_LIBCAP - /* if system have backtrace function */ #undef HAVE_LIBCTRACE @@ -347,18 +344,12 @@ int sigwait(const unsigned int *set, int *sig); /* Define if libxml2 was found */ #undef HAVE_LIBXML2 -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_CAPABILITY_H - /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_NETLINK_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_RTNETLINK_H -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_TYPES_H - /* Define if lmdb was found */ #undef HAVE_LMDB diff --git a/configure b/configure index d490beb58f..516c59017b 100755 --- a/configure +++ b/configure @@ -725,6 +725,7 @@ ISC_PLATFORM_USEDECLSPEC ISC_PLATFORM_RLIMITTYPE ISC_PLATFORM_HAVESTATNSEC ISC_PLATFORM_HAVESYSUNH +LIBCAP_LIBS ISC_PLATFORM_QUADFORMAT DST_EXTRA_SRCS DST_EXTRA_OBJS @@ -1701,7 +1702,7 @@ Optional Features: --enable-getifaddrs enable the use of getifaddrs() [yes|no]. --disable-isc-spnego use SPNEGO from GSSAPI library --disable-chroot disable chroot - --disable-linux-caps disable linux capabilities + --disable-linux-caps disable Linux capabilities --enable-atomic enable machine specific atomic operations [default=autodetect] --enable-fixed-rrset enable fixed rrset ordering [default=no] @@ -19795,26 +19796,27 @@ done no) ;; esac + +LIBCAP_LIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable Linux capabilities" >&5 +$as_echo_n "checking whether to enable Linux capabilities... " >&6; } # Check whether --enable-linux-caps was given. if test "${enable_linux_caps+set}" = set; then : enableval=$enable_linux_caps; +else + case $host in #( + *-linux*) : + enable_linux_caps=yes ;; #( + *) : + enable_linux_caps=no ;; +esac fi -case "$enable_linux_caps" in - yes|'') - for ac_header in linux/types.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_types_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_TYPES_H 1 -_ACEOF -fi - -done - - for ac_header in sys/capability.h +if test "$enable_linux_caps" = "yes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + for ac_header in sys/capability.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/capability.h" "ac_cv_header_sys_capability_h" "$ac_includes_default" if test "x$ac_cv_header_sys_capability_h" = xyes; then : @@ -19822,33 +19824,19 @@ if test "x$ac_cv_header_sys_capability_h" = xyes; then : #define HAVE_SYS_CAPABILITY_H 1 _ACEOF +else + as_fn_error $? "sys/capability.h header is required for Linux capabilities support" "$LINENO" 5 fi done - for ac_header in linux/capability.h -do : - ac_fn_c_check_header_compile "$LINENO" "linux/capability.h" "ac_cv_header_linux_capability_h" "#ifdef HAVE_LINUX_TYPES_H - #include - #endif - -" -if test "x$ac_cv_header_linux_capability_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LINUX_CAPABILITY_H 1 -_ACEOF - -fi - -done - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_set_proc in -lcap" >&5 -$as_echo_n "checking for cap_set_proc in -lcap... " >&6; } -if ${ac_cv_lib_cap_cap_set_proc+:} false; then : + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cap_set_proc" >&5 +$as_echo_n "checking for library containing cap_set_proc... " >&6; } +if ${ac_cv_search_cap_set_proc+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcap $LIBS" + ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19867,30 +19855,47 @@ return cap_set_proc (); return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_cap_cap_set_proc=yes -else - ac_cv_lib_cap_cap_set_proc=no +for ac_lib in '' cap; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_cap_set_proc=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + conftest$ac_exeext + if ${ac_cv_search_cap_set_proc+:} false; then : + break fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_cap_set_proc" >&5 -$as_echo "$ac_cv_lib_cap_cap_set_proc" >&6; } -if test "x$ac_cv_lib_cap_cap_set_proc" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBCAP 1 -_ACEOF - - LIBS="-lcap $LIBS" +done +if ${ac_cv_search_cap_set_proc+:} false; then : +else + ac_cv_search_cap_set_proc=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cap_set_proc" >&5 +$as_echo "$ac_cv_search_cap_set_proc" >&6; } +ac_res=$ac_cv_search_cap_set_proc +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + LIBCAP_LIBS="$ac_cv_search_cap_set_proc" +else + as_fn_error $? "libcap is required for Linux capabilities support" "$LINENO" 5 fi - ;; - no) - ;; -esac + LIBS="$save_LIBS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + for ac_header in sys/prctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" diff --git a/configure.in b/configure.in index b5b3a24a5b..60168f5f48 100644 --- a/configure.in +++ b/configure.in @@ -3570,23 +3570,30 @@ case "$enable_chroot" in no) ;; esac -AC_ARG_ENABLE(linux-caps, - AS_HELP_STRING([--disable-linux-caps], - [disable linux capabilities])) -case "$enable_linux_caps" in - yes|'') - AC_CHECK_HEADERS(linux/types.h) - AC_CHECK_HEADERS([sys/capability.h]) - AC_CHECK_HEADERS([linux/capability.h], [], [], - [#ifdef HAVE_LINUX_TYPES_H - #include - #endif - ]) - AC_CHECK_LIB(cap, cap_set_proc) - ;; - no) - ;; -esac + +LIBCAP_LIBS="" +AC_MSG_CHECKING([whether to enable Linux capabilities]) +AC_ARG_ENABLE([linux-caps], + [AS_HELP_STRING([--disable-linux-caps], + [disable Linux capabilities])], + [], + [AS_CASE([$host], + [*-linux*],[enable_linux_caps=yes], + [enable_linux_caps=no])]) + +AS_IF([test "$enable_linux_caps" = "yes"], + [AC_MSG_RESULT([yes]) + AC_CHECK_HEADERS([sys/capability.h], + [], + [AC_MSG_ERROR([sys/capability.h header is required for Linux capabilities support])]) + save_LIBS="$LIBS" + AC_SEARCH_LIBS([cap_set_proc], [cap], + [LIBCAP_LIBS="$ac_cv_search_cap_set_proc"], + [AC_MSG_ERROR([libcap is required for Linux capabilities support])]) + LIBS="$save_LIBS"], + [AC_MSG_RESULT([no])]) +AC_SUBST([LIBCAP_LIBS]) + AC_CHECK_HEADERS(sys/prctl.h) AC_CHECK_HEADERS(sys/un.h,