]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Only request permitted capabilities in non-libcap builds
authorMichał Kępień <michal@isc.org>
Tue, 26 Jun 2018 11:18:00 +0000 (13:18 +0200)
committerMichał Kępień <michal@isc.org>
Tue, 26 Jun 2018 11:20:39 +0000 (13:20 +0200)
While libcap-enabled builds check whether any capability named requests
is within the permitted capability set, non-libcap builds just try
requesting them, which potentially causes a misleading error message to
be output ("Operation not permitted: please ensure that the capset
kernel module is loaded").  Ensure non-libcap builds also check whether
any requested capability is within the permitted capability set.

(cherry picked from commit 8c66f32e53761dfa033dab3d366594683d24ce28)

bin/named/unix/os.c

index 951e3c4292d9cf631c2bc29d4ca9c1be93cc90b4..47ad5087662993242a295977c566d4d5f28c7776 100644 (file)
@@ -234,18 +234,47 @@ linux_setcaps(cap_t caps) {
                cap_free(curcaps); \
        } while (0)
 #else
-#define SET_CAP(flag) do { caps |= (1 << (flag)); } while (0)
+#define SET_CAP(flag) \
+       do { \
+               if (curcaps & (1 << (flag))) { \
+                       caps |= (1 << (flag)); \
+               } \
+       } while (0)
 #define INIT_CAP do { caps = 0; } while (0)
 #endif /* HAVE_LIBCAP */
 
+#ifndef HAVE_LIBCAP
+/*%
+ * Store the bitmask representing the permitted capability set in 'capsp'.  To
+ * match libcap-enabled behavior, capget() syscall errors are not reported,
+ * they just cause 'capsp' to be set to 0, which effectively prevents any
+ * capability from being subsequently requested.
+ */
+static void
+linux_getpermittedcaps(cap_t *capsp) {
+       struct __user_cap_header_struct caphead;
+       struct __user_cap_data_struct curcaps;
+
+       memset(&caphead, 0, sizeof(caphead));
+       caphead.version = _LINUX_CAPABILITY_VERSION;
+       caphead.pid = 0;
+       memset(&curcaps, 0, sizeof(curcaps));
+       syscall(SYS_capget, &caphead, &curcaps);
+
+       *capsp = curcaps.permitted;
+}
+#endif /* HAVE_LIBCAP */
+
 static void
 linux_initialprivs(void) {
+       cap_t curcaps;
        cap_t caps;
 #ifdef HAVE_LIBCAP
-       cap_t curcaps;
        cap_value_t capval;
        char strbuf[ISC_STRERRORSIZE];
        int err;
+#else
+       linux_getpermittedcaps(&curcaps);
 #endif
 
        /*%
@@ -310,12 +339,14 @@ linux_initialprivs(void) {
 
 static void
 linux_minprivs(void) {
+       cap_t curcaps;
        cap_t caps;
 #ifdef HAVE_LIBCAP
-       cap_t curcaps;
        cap_value_t capval;
        char strbuf[ISC_STRERRORSIZE];
        int err;
+#else
+       linux_getpermittedcaps(&curcaps);
 #endif
 
        INIT_CAP;