From: Michał Kępień Date: Tue, 26 Jun 2018 11:18:00 +0000 (+0200) Subject: Only request permitted capabilities in non-libcap builds X-Git-Tag: v9.9.13rc2~4^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bdf93ee7896f4055f862ae82e6eadcf35f7f9cc9;p=thirdparty%2Fbind9.git Only request permitted capabilities in non-libcap builds 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) --- diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index 951e3c4292d..47ad5087662 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -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;