src/daemon/common.c: Rewrite check_capability() using cap_get_bound().
authorFlorian Forster <octo@collectd.org>
Fri, 28 Oct 2016 13:04:11 +0000 (15:04 +0200)
committerFlorian Forster <octo@collectd.org>
Fri, 28 Oct 2016 13:04:11 +0000 (15:04 +0200)
capget(2) is Linux specific and the use of the raw syscalls is
discouraged. Also, there have been interesting crashes on some systems.

Issue: #2009

configure.ac
src/daemon/Makefile.am
src/daemon/common.c

index 9a6da11..4ccb893 100644 (file)
@@ -808,7 +808,20 @@ fi
 have_cpuid_h="no"
 AC_CHECK_HEADERS(cpuid.h, [have_cpuid_h="yes"])
 
-AC_CHECK_HEADERS(sys/capability.h)
+have_capability="yes"
+AC_CHECK_HEADERS(sys/capability.h,
+                 [have_capability="yes"],
+                 [have_capability="no (<sys/capability.h> not found)"])
+if test "x$have_capability" = "xyes"; then
+AC_CHECK_LIB(cap, cap_get_bound,
+                 [have_capability="yes"],
+                 [have_capability="no (cap_get_bound() not found)"])
+fi
+if test "x$have_capability" = "xyes"; then
+  AC_DEFINE(HAVE_CAPABILITY, 1, [Define to 1 if you have cap_get_bound() (-lcap).])
+fi
+AM_CONDITIONAL(BUILD_WITH_CAPABILITY, test "x$have_capability" = "xyes")
+
 #
 # Checks for typedefs, structures, and compiler characteristics.
 #
index 632872a..cb62c64 100644 (file)
@@ -11,6 +11,9 @@ AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
 
 # Link to these libraries..
 COMMON_LIBS = $(PTHREAD_LIBS)
+if BUILD_WITH_CAPABILITY
+COMMON_LIBS += -lcap
+endif
 if BUILD_WITH_LIBRT
 COMMON_LIBS += -lrt
 endif
index 477d759..212d72c 100644 (file)
@@ -60,7 +60,7 @@
 # include <arpa/inet.h>
 #endif
 
-#ifdef HAVE_SYS_CAPABILITY_H
+#if HAVE_CAPABILITY
 # include <sys/capability.h>
 #endif
 
@@ -1678,51 +1678,25 @@ void strarray_free (char **array, size_t array_len) /* {{{ */
        sfree (array);
 } /* }}} void strarray_free */
 
-#ifdef HAVE_SYS_CAPABILITY_H
-int check_capability (int capability) /* {{{ */
+#if HAVE_CAPABILITY
+int check_capability (int arg) /* {{{ */
 {
-#ifdef _LINUX_CAPABILITY_VERSION_3
-       cap_user_header_t cap_header = calloc(1, sizeof (*cap_header));
-       if (cap_header == NULL)
-       {
-               ERROR("check_capability: calloc failed");
-               return (-1);
-       }
+       cap_value_t cap = (cap_value_t) arg;
 
-       cap_user_data_t cap_data = calloc(1, sizeof (*cap_data));
-       if (cap_data == NULL)
-       {
-               ERROR("check_capability: calloc failed");
-               sfree(cap_header);
+       if (!CAP_IS_SUPPORTED (cap))
                return (-1);
-       }
 
-       cap_header->pid = getpid();
-       cap_header->version = _LINUX_CAPABILITY_VERSION_3;
-       if (capget(cap_header, cap_data) < 0)
-       {
-               ERROR("check_capability: capget failed");
-               sfree(cap_header);
-               sfree(cap_data);
+       int have_cap = cap_get_bound (cap);
+       if (have_cap != 1)
                return (-1);
-       }
 
-       if ((cap_data->effective & (1 << capability)) == 0)
-       {
-               sfree(cap_header);
-               sfree(cap_data);
-               return (-1);
-       }
-       else
-       {
-               sfree(cap_header);
-               sfree(cap_data);
-               return (0);
-       }
+       return (0);
+} /* }}} int check_capability */
 #else
+int check_capability (__attribute__((unused)) int arg) /* {{{ */
+{
        WARNING ("check_capability: unsupported capability implementation. "
-           "Some plugin(s) may require elevated privileges to work properly.");
+                "Some plugin(s) may require elevated privileges to work properly.");
        return (0);
-#endif /* _LINUX_CAPABILITY_VERSION_3 */
 } /* }}} int check_capability */
-#endif /* HAVE_SYS_CAPABILITY_H */
+#endif /* HAVE_CAPABILITY */