From 6186cd1cf6e180f45ad7fe79583172651bdf4c19 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 17 Mar 2019 10:57:48 +0100 Subject: [PATCH 01/13] Check capabilities with kernel methods. Removes the need for libcap on the target system. Signed-off-by: DL6ER --- Makefile | 2 +- capabilities.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 6f7f78c7b..009e18f01 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ CCFLAGS=-std=gnu11 -I$(IDIR) $(WARNFLAGS) -D_FILE_OFFSET_BITS=64 $(HARDENING_FLA # for dnsmasq we need the nettle crypto library and the gmp maths library # We link the two libraries statically. Although this increases the binary file size by about 1 MB, it saves about 5 MB of shared libraries and makes deployment easier #LIBS=-pthread -lnettle -lgmp -lhogweed -LIBS=-pthread -lrt -lcap -Wl,-Bstatic -L/usr/local/lib -lhogweed -lgmp -lnettle -Wl,-Bdynamic +LIBS=-pthread -lrt -Wl,-Bstatic -L/usr/local/lib -lhogweed -lgmp -lnettle -Wl,-Bdynamic # Flags for compiling with libidn : -lidn # Flags for compiling with libidn2: -lidn2 diff --git a/capabilities.c b/capabilities.c index 1a33fee83..a583f440f 100644 --- a/capabilities.c +++ b/capabilities.c @@ -8,36 +8,68 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ +// Definition of LINUX_CAPABILITY_VERSION_* +#define FTLDNS +#include "dnsmasq/dnsmasq.h" +#undef __USE_XOPEN #include "FTL.h" -#include bool check_capabilities() { - if(!cap_get_bound(CAP_NET_ADMIN)) + int capsize = 1; /* for header version 1 */ + cap_user_header_t hdr = NULL; + cap_user_data_t data = NULL; + + /* find version supported by kernel */ + hdr = calloc(sizeof(*hdr), capsize); + memset(hdr, 0, sizeof(*hdr)); + capget(hdr, NULL); + + if (hdr->version != LINUX_CAPABILITY_VERSION_1) + { + /* if unknown version, use largest supported version (3) */ + if (hdr->version != LINUX_CAPABILITY_VERSION_2) + hdr->version = LINUX_CAPABILITY_VERSION_3; + capsize = 2; + } + + data = calloc(sizeof(*data), capsize); + capget(hdr, data); /* Get current values, for verification */ + + bool missing = true; + if (!(data->permitted & (1 << CAP_NET_ADMIN))) { // Needed for ARP-injection (used when we're the DHCP server) logg("**************************************************************"); logg("WARNING: Required linux capability CAP_NET_ADMIN not available"); logg("**************************************************************"); - return false; + missing = true; } - if(!cap_get_bound(CAP_NET_RAW)) + if (!(data->permitted & (1 << CAP_NET_RAW))) { // Needed for raw socket access (necessary for ICMP) logg("************************************************************"); logg("WARNING: Required linux capability CAP_NET_RAW not available"); logg("************************************************************"); - return false; + missing = true; } - if(!cap_get_bound(CAP_NET_BIND_SERVICE)) + if (!(data->permitted & (1 << CAP_NET_BIND_SERVICE))) { // Necessary for dynamic port binding logg("*********************************************************************"); logg("WARNING: Required linux capability CAP_NET_BIND_SERVICE not available"); logg("*********************************************************************"); - return false; + missing = true; + } + if (!(data->permitted & (1 << CAP_SETUID))) + { + // Necessary for changing our own user ID ("daemonizing") + logg("*********************************************************************"); + logg("WARNING: Required linux capability CAP_SETUID not available"); + logg("*********************************************************************"); + missing = true; } // All okay! - return true; + return missing; } From 8d615d6011fa839e4d7b55329a13b23b500ea0b6 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 17 Mar 2019 14:53:27 +0100 Subject: [PATCH 02/13] Add capabilities debug mode that prints all capabilities which are enabled when pihole-FTL is started. Signed-off-by: DL6ER --- FTL.h | 1 + capabilities.c | 39 +++++++++++++++++++++++++++++---------- config.c | 7 +++++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/FTL.h b/FTL.h index 7c2cf88c7..a4bba0955 100644 --- a/FTL.h +++ b/FTL.h @@ -104,6 +104,7 @@ enum { DEBUG_API = (1 << 9), /* 00000010 00000000 */ DEBUG_OVERTIME = (1 << 10), /* 00000100 00000000 */ DEBUG_EXTBLOCKED = (1 << 11), /* 00001000 00000000 */ + DEBUG_CAPS = (1 << 12), /* 00010000 00000000 */ }; // Database table "ftl" diff --git a/capabilities.c b/capabilities.c index a583f440f..16a77e751 100644 --- a/capabilities.c +++ b/capabilities.c @@ -14,6 +14,9 @@ #undef __USE_XOPEN #include "FTL.h" +const int capabilityIntegers[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; +const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; + bool check_capabilities() { int capsize = 1; /* for header version 1 */ @@ -36,22 +39,38 @@ bool check_capabilities() data = calloc(sizeof(*data), capsize); capget(hdr, data); /* Get current values, for verification */ - bool missing = true; + if(config.debug & DEBUG_CAPS) + { + logg("*********************************************************************"); + for(unsigned int i = 0u; i < (sizeof(capabilityIntegers)/sizeof(const int)); i++) + { + unsigned int capid = capabilityIntegers[i]; + logg("DEBUG: Capability %-24s (%02u) = %s%s%s", + capabilityNames[capid], + capid, + ((data->effective & (1 << capid)) ? "E":"-"), + ((data->permitted & (1 << capid)) ? "P":"-"), + ((data->inheritable & (1 << capid)) ? "I":"-")); + } + logg("*********************************************************************"); + } + + bool capabilities_okay = true; if (!(data->permitted & (1 << CAP_NET_ADMIN))) { // Needed for ARP-injection (used when we're the DHCP server) - logg("**************************************************************"); + logg("*********************************************************************"); logg("WARNING: Required linux capability CAP_NET_ADMIN not available"); - logg("**************************************************************"); - missing = true; + logg("*********************************************************************"); + capabilities_okay = false; } if (!(data->permitted & (1 << CAP_NET_RAW))) { // Needed for raw socket access (necessary for ICMP) - logg("************************************************************"); + logg("*********************************************************************"); logg("WARNING: Required linux capability CAP_NET_RAW not available"); - logg("************************************************************"); - missing = true; + logg("*********************************************************************"); + capabilities_okay = false; } if (!(data->permitted & (1 << CAP_NET_BIND_SERVICE))) { @@ -59,7 +78,7 @@ bool check_capabilities() logg("*********************************************************************"); logg("WARNING: Required linux capability CAP_NET_BIND_SERVICE not available"); logg("*********************************************************************"); - missing = true; + capabilities_okay = false; } if (!(data->permitted & (1 << CAP_SETUID))) { @@ -67,9 +86,9 @@ bool check_capabilities() logg("*********************************************************************"); logg("WARNING: Required linux capability CAP_SETUID not available"); logg("*********************************************************************"); - missing = true; + capabilities_okay = false; } // All okay! - return missing; + return capabilities_okay; } diff --git a/config.c b/config.c index a2f68ba9d..c867a6a79 100644 --- a/config.c +++ b/config.c @@ -594,6 +594,12 @@ void read_debuging_settings(FILE *fp) if(buffer != NULL && strcasecmp(buffer, "true") == 0) config.debug |= DEBUG_EXTBLOCKED; + // DEBUG_CAPS + // defaults to: false + buffer = parse_FTLconf(fp, "DEBUG_CAPS"); + if(buffer != NULL && strcasecmp(buffer, "true") == 0) + config.debug |= DEBUG_CAPS; + // DEBUG_ALL // defaults to: false buffer = parse_FTLconf(fp, "DEBUG_ALL"); @@ -616,6 +622,7 @@ void read_debuging_settings(FILE *fp) logg("* DEBUG_API %s *", (config.debug & DEBUG_API)? "YES":"NO "); logg("* DEBUG_OVERTIME %s *", (config.debug & DEBUG_OVERTIME)? "YES":"NO "); logg("* DEBUG_EXTBLOCKED %s *", (config.debug & DEBUG_EXTBLOCKED)? "YES":"NO "); + logg("* DEBUG_CAPS %s *", (config.debug & DEBUG_CAPS)? "YES":"NO "); logg("************************"); } From 73cbb911ae8b2a4ab8e013a56b2bafb22e9dd4c7 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 17 Mar 2019 15:30:05 +0100 Subject: [PATCH 03/13] Change caps sorting in debug messages. The prefered order seems to be PIE. Signed-off-by: DL6ER --- capabilities.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/capabilities.c b/capabilities.c index 16a77e751..77cb9da9b 100644 --- a/capabilities.c +++ b/capabilities.c @@ -48,9 +48,9 @@ bool check_capabilities() logg("DEBUG: Capability %-24s (%02u) = %s%s%s", capabilityNames[capid], capid, - ((data->effective & (1 << capid)) ? "E":"-"), ((data->permitted & (1 << capid)) ? "P":"-"), - ((data->inheritable & (1 << capid)) ? "I":"-")); + ((data->inheritable & (1 << capid)) ? "I":"-"), + ((data->effective & (1 << capid)) ? "E":"-")); } logg("*********************************************************************"); } From 4a15b93fea64cf86cdb422b898f75818a5a2f2f5 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 17 Mar 2019 15:33:04 +0100 Subject: [PATCH 04/13] Explicitly check availability of capability in current kernel before printing its value. Accessing a capability that is not valid can never lead to a crash, however, it is also no a menaingful thing to do so we don't do it. Signed-off-by: DL6ER --- capabilities.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/capabilities.c b/capabilities.c index 77cb9da9b..5ae71709a 100644 --- a/capabilities.c +++ b/capabilities.c @@ -45,6 +45,12 @@ bool check_capabilities() for(unsigned int i = 0u; i < (sizeof(capabilityIntegers)/sizeof(const int)); i++) { unsigned int capid = capabilityIntegers[i]; + + // Check if capability is valid for the current kernel + // If not, exit loop early + if(!cap_valid(capid)) + break; + logg("DEBUG: Capability %-24s (%02u) = %s%s%s", capabilityNames[capid], capid, From 35daec46d67116669d00d66ff588609e7852adc6 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 17 Mar 2019 15:35:45 +0100 Subject: [PATCH 05/13] Print current set of capabilities when receiving SIGHUP and DEBUG_CAPS is set to true. Signed-off-by: DL6ER --- dnsmasq_interface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dnsmasq_interface.c b/dnsmasq_interface.c index 7b396cc49..690c8e0fb 100644 --- a/dnsmasq_interface.c +++ b/dnsmasq_interface.c @@ -382,6 +382,10 @@ void FTL_dnsmasq_reload(void) // Reread pihole-FTL.conf to see which debugging flags are set read_debuging_settings(NULL); + + // Print current set of capabilities if requested via debug flag + if(config.debug & DEBUG_CAPS) + check_capabilities(); } void _FTL_reply(unsigned short flags, char *name, struct all_addr *addr, int id, const char* file, const int line) From 91beeec82425075a9e40ccb7d0fc478dfa9ff05f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 18 Mar 2019 06:57:48 +0100 Subject: [PATCH 06/13] Free allocated memory Signed-off-by: DL6ER --- capabilities.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/capabilities.c b/capabilities.c index 5ae71709a..b5f9438e8 100644 --- a/capabilities.c +++ b/capabilities.c @@ -19,25 +19,35 @@ const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ bool check_capabilities() { - int capsize = 1; /* for header version 1 */ - cap_user_header_t hdr = NULL; + // First assume header version 1 + int capsize = VFS_CAP_U32_1; cap_user_data_t data = NULL; + cap_user_header_t hdr = calloc(sizeof(*hdr), capsize); - /* find version supported by kernel */ - hdr = calloc(sizeof(*hdr), capsize); + // Determine capabilities version used by the current kernel memset(hdr, 0, sizeof(*hdr)); capget(hdr, NULL); + // Check version if (hdr->version != LINUX_CAPABILITY_VERSION_1) { - /* if unknown version, use largest supported version (3) */ - if (hdr->version != LINUX_CAPABILITY_VERSION_2) - hdr->version = LINUX_CAPABILITY_VERSION_3; - capsize = 2; + // If unknown version, use largest supported version (3) + // Version 2 is deprecated according to linux/capability.h + if (hdr->version != LINUX_CAPABILITY_VERSION_2) + { + hdr->version = LINUX_CAPABILITY_VERSION_3; + capsize = VFS_CAP_U32_3; + } + else + { + // Use version 2 + capsize = VFS_CAP_U32_2; + } } + // Get current capabilities data = calloc(sizeof(*data), capsize); - capget(hdr, data); /* Get current values, for verification */ + capget(hdr, data); if(config.debug & DEBUG_CAPS) { @@ -95,6 +105,10 @@ bool check_capabilities() capabilities_okay = false; } + // Free allocated memory + free(hdr); + free(data); + // All okay! return capabilities_okay; } From efbe69cdf26f5ba88e8ce3c6f11c3417264828eb Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 18 Mar 2019 07:42:04 +0100 Subject: [PATCH 07/13] Declare array only to be used within capabilitites.c as static Signed-off-by: DL6ER --- capabilities.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/capabilities.c b/capabilities.c index b5f9438e8..c671969de 100644 --- a/capabilities.c +++ b/capabilities.c @@ -14,8 +14,9 @@ #undef __USE_XOPEN #include "FTL.h" -const int capabilityIntegers[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; -const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; +static const int capabilityIntegers[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; +static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; +static const int numCaps = sizeof(capabilityIntegers)/sizeof(const int); bool check_capabilities() { @@ -52,7 +53,7 @@ bool check_capabilities() if(config.debug & DEBUG_CAPS) { logg("*********************************************************************"); - for(unsigned int i = 0u; i < (sizeof(capabilityIntegers)/sizeof(const int)); i++) + for(unsigned int i = 0u; i < numCaps; i++) { unsigned int capid = capabilityIntegers[i]; @@ -62,8 +63,7 @@ bool check_capabilities() break; logg("DEBUG: Capability %-24s (%02u) = %s%s%s", - capabilityNames[capid], - capid, + capabilityNames[capid], capid, ((data->permitted & (1 << capid)) ? "P":"-"), ((data->inheritable & (1 << capid)) ? "I":"-"), ((data->effective & (1 << capid)) ? "E":"-")); From f48fa15040cf9463324ddacbb1a550780d96705b Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 18 Mar 2019 07:48:56 +0100 Subject: [PATCH 08/13] Use actual values for capsize as the macros are not available on all CI machines, causing the jobs to fail. Signed-off-by: DL6ER --- capabilities.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/capabilities.c b/capabilities.c index c671969de..f1ccdf996 100644 --- a/capabilities.c +++ b/capabilities.c @@ -16,12 +16,12 @@ static const int capabilityIntegers[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; -static const int numCaps = sizeof(capabilityIntegers)/sizeof(const int); +static const unsigned int numCaps = sizeof(capabilityIntegers)/sizeof(const int); bool check_capabilities() { // First assume header version 1 - int capsize = VFS_CAP_U32_1; + int capsize = 1; // VFS_CAP_U32_1 cap_user_data_t data = NULL; cap_user_header_t hdr = calloc(sizeof(*hdr), capsize); @@ -37,12 +37,12 @@ bool check_capabilities() if (hdr->version != LINUX_CAPABILITY_VERSION_2) { hdr->version = LINUX_CAPABILITY_VERSION_3; - capsize = VFS_CAP_U32_3; + capsize = 2; // VFS_CAP_U32_3 } else { // Use version 2 - capsize = VFS_CAP_U32_2; + capsize = 2; // VFS_CAP_U32_2 } } From 526ec7e27b92435797235a3495a829895134a5a3 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 18 Mar 2019 11:43:15 +0100 Subject: [PATCH 09/13] Missing CAP_SETUID is not a problem as we only need it when we start as root (which has all capabiltites). Signed-off-by: DL6ER --- capabilities.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/capabilities.c b/capabilities.c index f1ccdf996..35a6a2617 100644 --- a/capabilities.c +++ b/capabilities.c @@ -96,14 +96,6 @@ bool check_capabilities() logg("*********************************************************************"); capabilities_okay = false; } - if (!(data->permitted & (1 << CAP_SETUID))) - { - // Necessary for changing our own user ID ("daemonizing") - logg("*********************************************************************"); - logg("WARNING: Required linux capability CAP_SETUID not available"); - logg("*********************************************************************"); - capabilities_okay = false; - } // Free allocated memory free(hdr); From f7af506ab516f3f37f8ff78916806003ff42a232 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 18 Mar 2019 11:51:57 +0100 Subject: [PATCH 10/13] Print message that we received SIGHUP into pihole-FTL.log when this happens Signed-off-by: DL6ER --- capabilities.c | 24 ++++++++++++------------ dnsmasq_interface.c | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/capabilities.c b/capabilities.c index 35a6a2617..4bd16b536 100644 --- a/capabilities.c +++ b/capabilities.c @@ -52,7 +52,7 @@ bool check_capabilities() if(config.debug & DEBUG_CAPS) { - logg("*********************************************************************"); + logg("*********************************************************"); for(unsigned int i = 0u; i < numCaps; i++) { unsigned int capid = capabilityIntegers[i]; @@ -62,38 +62,38 @@ bool check_capabilities() if(!cap_valid(capid)) break; - logg("DEBUG: Capability %-24s (%02u) = %s%s%s", + logg("* DEBUG: Capability %-24s (%02u) = %s%s%s *", capabilityNames[capid], capid, ((data->permitted & (1 << capid)) ? "P":"-"), ((data->inheritable & (1 << capid)) ? "I":"-"), ((data->effective & (1 << capid)) ? "E":"-")); } - logg("*********************************************************************"); + logg("*********************************************************"); } bool capabilities_okay = true; if (!(data->permitted & (1 << CAP_NET_ADMIN))) { // Needed for ARP-injection (used when we're the DHCP server) - logg("*********************************************************************"); - logg("WARNING: Required linux capability CAP_NET_ADMIN not available"); - logg("*********************************************************************"); + logg("*************************************************************************"); + logg("* WARNING: Required Linux capability CAP_NET_ADMIN not available *"); + logg("*************************************************************************"); capabilities_okay = false; } if (!(data->permitted & (1 << CAP_NET_RAW))) { // Needed for raw socket access (necessary for ICMP) - logg("*********************************************************************"); - logg("WARNING: Required linux capability CAP_NET_RAW not available"); - logg("*********************************************************************"); + logg("*************************************************************************"); + logg("* WARNING: Required Linux capability CAP_NET_RAW not available *"); + logg("*************************************************************************"); capabilities_okay = false; } if (!(data->permitted & (1 << CAP_NET_BIND_SERVICE))) { // Necessary for dynamic port binding - logg("*********************************************************************"); - logg("WARNING: Required linux capability CAP_NET_BIND_SERVICE not available"); - logg("*********************************************************************"); + logg("*************************************************************************"); + logg("* WARNING: Required Linux capability CAP_NET_BIND_SERVICE not available *"); + logg("*************************************************************************"); capabilities_okay = false; } diff --git a/dnsmasq_interface.c b/dnsmasq_interface.c index 690c8e0fb..a62945f36 100644 --- a/dnsmasq_interface.c +++ b/dnsmasq_interface.c @@ -361,6 +361,8 @@ void FTL_dnsmasq_reload(void) // *before* clearing the cache and rereading the lists // This is the only hook that is not skipped in PRIVACY_NOSTATS mode + logg("Received SIGHUP, reloading cache"); + // Called when dnsmasq re-reads its config and hosts files // Reset number of blocked domains counters->gravity = 0; From dbf6e0831eea5f9d74353f18127b90512f5edad2 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 18 Mar 2019 12:00:25 +0100 Subject: [PATCH 11/13] Prettify capabilities debugging output Signed-off-by: DL6ER --- capabilities.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/capabilities.c b/capabilities.c index 4bd16b536..dd20089ab 100644 --- a/capabilities.c +++ b/capabilities.c @@ -14,9 +14,9 @@ #undef __USE_XOPEN #include "FTL.h" -static const int capabilityIntegers[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; -static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; -static const unsigned int numCaps = sizeof(capabilityIntegers)/sizeof(const int); +static const unsigned int capabilityIDs[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; +static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; +static const unsigned int numCaps = sizeof(capabilityIDs) / sizeof(const int); bool check_capabilities() { @@ -52,23 +52,24 @@ bool check_capabilities() if(config.debug & DEBUG_CAPS) { - logg("*********************************************************"); + logg("***************************************"); + logg("* Linux capability debugging enabled *"); for(unsigned int i = 0u; i < numCaps; i++) { - unsigned int capid = capabilityIntegers[i]; + const unsigned int capid = capabilityIDs[i]; // Check if capability is valid for the current kernel // If not, exit loop early if(!cap_valid(capid)) break; - logg("* DEBUG: Capability %-24s (%02u) = %s%s%s *", + logg("* %-24s (%02u) = %s%s%s *", capabilityNames[capid], capid, - ((data->permitted & (1 << capid)) ? "P":"-"), + ((data->permitted & (1 << capid)) ? "P":"-"), ((data->inheritable & (1 << capid)) ? "I":"-"), - ((data->effective & (1 << capid)) ? "E":"-")); + ((data->effective & (1 << capid)) ? "E":"-")); } - logg("*********************************************************"); + logg("***************************************"); } bool capabilities_okay = true; From 9461e0c9b08f875c7911d77aa0772caf25c21f17 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 19 Mar 2019 06:55:19 +0100 Subject: [PATCH 12/13] Review comments Signed-off-by: DL6ER --- capabilities.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/capabilities.c b/capabilities.c index dd20089ab..5bb39e327 100644 --- a/capabilities.c +++ b/capabilities.c @@ -26,7 +26,6 @@ bool check_capabilities() cap_user_header_t hdr = calloc(sizeof(*hdr), capsize); // Determine capabilities version used by the current kernel - memset(hdr, 0, sizeof(*hdr)); capget(hdr, NULL); // Check version @@ -102,6 +101,6 @@ bool check_capabilities() free(hdr); free(data); - // All okay! + // Return whether capabilities are all okay return capabilities_okay; } From 09f0727e04e9fe2a3c51816340d8f0b8e1682489 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 19 Mar 2019 07:35:50 +0100 Subject: [PATCH 13/13] Type of capabilityIDs is const unsigned int Signed-off-by: DL6ER --- capabilities.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capabilities.c b/capabilities.c index 5bb39e327..9290cc2c4 100644 --- a/capabilities.c +++ b/capabilities.c @@ -16,7 +16,7 @@ static const unsigned int capabilityIDs[] = { CAP_CHOWN , CAP_DAC_OVERRIDE , CAP_DAC_READ_SEARCH , CAP_FOWNER , CAP_FSETID , CAP_KILL , CAP_SETGID , CAP_SETUID , CAP_SETPCAP , CAP_LINUX_IMMUTABLE , CAP_NET_BIND_SERVICE , CAP_NET_BROADCAST , CAP_NET_ADMIN , CAP_NET_RAW , CAP_IPC_LOCK , CAP_IPC_OWNER , CAP_SYS_MODULE , CAP_SYS_RAWIO , CAP_SYS_CHROOT , CAP_SYS_PTRACE , CAP_SYS_PACCT , CAP_SYS_ADMIN , CAP_SYS_BOOT , CAP_SYS_NICE , CAP_SYS_RESOURCE , CAP_SYS_TIME , CAP_SYS_TTY_CONFIG , CAP_MKNOD , CAP_LEASE , CAP_AUDIT_WRITE , CAP_AUDIT_CONTROL , CAP_SETFCAP , CAP_MAC_OVERRIDE , CAP_MAC_ADMIN , CAP_SYSLOG , CAP_WAKE_ALARM , CAP_BLOCK_SUSPEND , CAP_AUDIT_READ }; static const char* capabilityNames[] = {"CAP_CHOWN", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_FOWNER", "CAP_FSETID", "CAP_KILL", "CAP_SETGID", "CAP_SETUID", "CAP_SETPCAP", "CAP_LINUX_IMMUTABLE", "CAP_NET_BIND_SERVICE", "CAP_NET_BROADCAST", "CAP_NET_ADMIN", "CAP_NET_RAW", "CAP_IPC_LOCK", "CAP_IPC_OWNER", "CAP_SYS_MODULE", "CAP_SYS_RAWIO", "CAP_SYS_CHROOT", "CAP_SYS_PTRACE", "CAP_SYS_PACCT", "CAP_SYS_ADMIN", "CAP_SYS_BOOT", "CAP_SYS_NICE", "CAP_SYS_RESOURCE", "CAP_SYS_TIME", "CAP_SYS_TTY_CONFIG", "CAP_MKNOD", "CAP_LEASE", "CAP_AUDIT_WRITE", "CAP_AUDIT_CONTROL", "CAP_SETFCAP", "CAP_MAC_OVERRIDE", "CAP_MAC_ADMIN", "CAP_SYSLOG", "CAP_WAKE_ALARM", "CAP_BLOCK_SUSPEND", "CAP_AUDIT_READ"}; -static const unsigned int numCaps = sizeof(capabilityIDs) / sizeof(const int); +static const unsigned int numCaps = sizeof(capabilityIDs) / sizeof(const unsigned int); bool check_capabilities() {