From 3dd314590e37dd76d4e1f2c81fc1c07d3d149b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 26 Jun 2018 14:52:11 +0200 Subject: [PATCH] Make libcap mandatory when Linux capabilities are enabled --- bin/named/Makefile.in | 6 +- bin/named/unix/os.c | 86 ++++++-------------------- config.h.in | 9 +-- configure | 137 +++++++++++++++++++++++------------------- configure.in | 40 ++++++------ 5 files changed, 123 insertions(+), 155 deletions(-) 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..0d1d8290cd 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -61,14 +61,14 @@ static int singletonfd = -1; /* * If there's no , we don't care about */ -#ifndef HAVE_LINUX_CAPABILITY_H +#ifndef WANT_LINUX_CAPABILITY #undef HAVE_SYS_PRCTL_H #endif /* * Linux defines: * (T) HAVE_LINUXTHREADS - * (C) HAVE_SYS_CAPABILITY_H (or HAVE_LINUX_CAPABILITY_H) + * (C) WANT_LINUX_CAPABILITY * (P) HAVE_SYS_PRCTL_H * The possible cases are: * none: setuid() normally @@ -110,35 +110,18 @@ 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 +#if WANT_LINUX_CAPABILITY static isc_boolean_t non_root = ISC_FALSE; static isc_boolean_t non_root_caps = ISC_FALSE; -#ifdef HAVE_SYS_CAPABILITY_H +#if 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 +#if WANT_LINUX_CAPABILITY && HAVE_SYS_PRCTL_H #include /* Required for prctl(). */ /* @@ -153,46 +136,22 @@ static isc_boolean_t non_root_caps = ISC_FALSE; #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 +189,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 +253,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,12 +286,10 @@ linux_minprivs(void) { linux_setcaps(caps); -#ifdef HAVE_LIBCAP FREE_CAP; -#endif } -#ifdef HAVE_SYS_PRCTL_H +#if WANT_LINUX_CAPABILITY && HAVE_SYS_PRCTL_H static void linux_keepcaps(void) { char strbuf[ISC_STRERRORSIZE]; @@ -364,7 +311,7 @@ linux_keepcaps(void) { } #endif -#endif /* HAVE_LINUX_CAPABILITY_H */ +#endif /* WANT_LINUX_CAPABILITY */ static void @@ -381,7 +328,7 @@ setup_syslog(const char *progname) { void named_os_init(const char *progname) { setup_syslog(progname); -#ifdef HAVE_LINUX_CAPABILITY_H +#if WANT_LINUX_CAPABILITY linux_initialprivs(); #endif #ifdef HAVE_LINUXTHREADS @@ -567,11 +514,12 @@ named_os_changeuser(void) { done_setuid = ISC_TRUE; #ifdef HAVE_LINUXTHREADS -#ifdef HAVE_LINUX_CAPABILITY_H - if (!non_root_caps) +#if WANT_LINUX_CAPABILITY + 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 +548,7 @@ named_os_changeuser(void) { strbuf); } #endif -#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS) +#if defined(WANT_LINUX_CAPABILITY) && !defined(HAVE_LINUXTHREADS) linux_minprivs(); #endif } @@ -632,7 +580,7 @@ named_os_adjustnofile(void) { void named_os_minprivs(void) { -#ifdef HAVE_SYS_PRCTL_H +#if WANT_LINUX_CAPABILITY && HAVE_SYS_PRCTL_H linux_keepcaps(); #endif @@ -640,7 +588,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 WANT_LINUX_CAPABILITY && defined(HAVE_LINUXTHREADS) linux_minprivs(); #endif } diff --git a/config.h.in b/config.h.in index 686352be1b..99494f83b0 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 @@ -356,9 +353,6 @@ int sigwait(const unsigned int *set, int *sig); /* 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 @@ -626,6 +620,9 @@ int sigwait(const unsigned int *set, int *sig); /* the default value of dnssec-validation option */ #undef VALIDATION_DEFAULT +/* define if you want to have Linux capabilities support */ +#undef WANT_LINUX_CAPABILITY + /* Define to enable very verbose query trace logging. */ #undef WANT_QUERYTRACE diff --git a/configure b/configure index d490beb58f..edb67b7363 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,60 +19796,57 @@ 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; + 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 +case $enable_linux_caps in #( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WANT_LINUX_CAPABILITY 1" >>confdefs.h + + for ac_header in sys/capability.h linux/capability.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + : +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "sys/capability.h or linux/capability.h header not found (required for Linux capabilities) +See \`config.log' for more details" "$LINENO" 5; } fi done - 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 : - cat >>confdefs.h <<_ACEOF -#define HAVE_SYS_CAPABILITY_H 1 -_ACEOF - -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 : + { $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 +19865,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_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "libcap not found (required for Linux capabilities) +See \`config.log' for more details" "$LINENO" 5; } fi - ;; - no) - ;; + ;; esac + + 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..5e2d437895 100644 --- a/configure.in +++ b/configure.in @@ -3570,23 +3570,29 @@ 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_CASE([$enable_linux_caps], + [no],[AC_MSG_RESULT([no])], + [AC_MSG_RESULT([yes]) + AC_DEFINE([WANT_LINUX_CAPABILITY], [1], [define if you want to have Linux capabilities support]) + AC_CHECK_HEADERS([sys/capability.h linux/capability.h], [:], + [AC_MSG_FAILURE([sys/capability.h or linux/capability.h header not found (required for Linux capabilities)])]) + AC_SEARCH_LIBS([cap_set_proc], [cap], + [LIBCAP_LIBS="$ac_cv_search_cap_set_proc"], + [AC_MSG_FAILURE([libcap not found (required for Linux capabilities)])]) + ]) +AC_SUBST([LIBCAP_LIBS]) + AC_CHECK_HEADERS(sys/prctl.h) AC_CHECK_HEADERS(sys/un.h,