aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch
diff options
context:
space:
mode:
authorKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>2019-03-09 08:40:57 +0000
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>2019-07-25 12:23:46 +0100
commite9eec39aacde450ba87598d85987b374ce6aed95 (patch)
tree3823546edc4d7228951ea9e37f55f6fea3f06833 /package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch
parent7d684b7673a7cb4f3fef366dd4f621f62fc4019c (diff)
downloadupstream-e9eec39aacde450ba87598d85987b374ce6aed95.tar.gz
upstream-e9eec39aacde450ba87598d85987b374ce6aed95.tar.bz2
upstream-e9eec39aacde450ba87598d85987b374ce6aed95.zip
dnsmasq: backport latest patches
Backport upstream patches pre 2.81rc for testing purposes. Let's see what falls out! Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Diffstat (limited to 'package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch')
-rw-r--r--package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch203
1 files changed, 203 insertions, 0 deletions
diff --git a/package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch b/package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch
new file mode 100644
index 0000000000..828f5adfa0
--- /dev/null
+++ b/package/network/services/dnsmasq/patches/0045-Improve-kernel-capability-manipulation-code-under-Li.patch
@@ -0,0 +1,203 @@
+From 305ffb5ef0ba5ab1df32ef80f266a4c9e395ca13 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Sat, 16 Mar 2019 18:17:17 +0000
+Subject: [PATCH 45/57] Improve kernel-capability manipulation code under
+ Linux.
+
+Dnsmasq now fails early if a required capability is not available,
+and tries not to request capabilities not required by its
+configuration.
+
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ CHANGELOG | 7 ++-
+ src/dnsmasq.c | 119 +++++++++++++++++++++++++++++++++-----------------
+ 2 files changed, 84 insertions(+), 42 deletions(-)
+
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -28,7 +28,12 @@ version 2.81
+
+ Support TCP-fastopen (RFC-7413) on both incoming and
+ outgoing TCP connections, if supported and enabled in the OS.
+-
++
++ Improve kernel-capability manipulation code under Linux. Dnsmasq
++ now fails early if a required capability is not available, and
++ tries not to request capabilities not required by its
++ configuration.
++
+
+ version 2.80
+ Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -52,6 +52,9 @@ int main (int argc, char **argv)
+ #if defined(HAVE_LINUX_NETWORK)
+ cap_user_header_t hdr = NULL;
+ cap_user_data_t data = NULL;
++ int need_cap_net_admin = 0;
++ int need_cap_net_raw = 0;
++ int need_cap_net_bind_service = 0;
+ char *bound_device = NULL;
+ int did_bind = 0;
+ #endif
+@@ -285,11 +288,24 @@ int main (int argc, char **argv)
+ }
+
+ if (daemon->dhcp || daemon->relay4)
+- dhcp_init();
++ {
++ dhcp_init();
++# ifdef HAVE_LINUX_NETWORK
++ if (!option_bool(OPT_NO_PING))
++ need_cap_net_raw = 1;
++ need_cap_net_admin = 1;
++# endif
++ }
+
+ # ifdef HAVE_DHCP6
+ if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
+- ra_init(now);
++ {
++ ra_init(now);
++# ifdef HAVE_LINUX_NETWORK
++ need_cap_net_raw = 1;
++ need_cap_net_admin = 1;
++# endif
++ }
+
+ if (daemon->doing_dhcp6 || daemon->relay6)
+ dhcp6_init();
+@@ -299,7 +315,12 @@ int main (int argc, char **argv)
+
+ #ifdef HAVE_IPSET
+ if (daemon->ipsets)
+- ipset_init();
++ {
++ ipset_init();
++# ifdef HAVE_LINUX_NETWORK
++ need_cap_net_admin = 1;
++# endif
++ }
+ #endif
+
+ #if defined(HAVE_LINUX_NETWORK)
+@@ -440,28 +461,58 @@ int main (int argc, char **argv)
+ }
+
+ #if defined(HAVE_LINUX_NETWORK)
++ /* We keep CAP_NETADMIN (for ARP-injection) and
++ CAP_NET_RAW (for icmp) if we're doing dhcp,
++ if we have yet to bind ports because of DAD,
++ or we're doing it dynamically,
++ we need CAP_NET_BIND_SERVICE. */
++ if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
++ (option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
++ need_cap_net_bind_service = 1;
++
+ /* determine capability API version here, while we can still
+ call safe_malloc */
+- if (ent_pw && ent_pw->pw_uid != 0)
++ int capsize = 1; /* for header version 1 */
++ char *fail = NULL;
++
++ hdr = safe_malloc(sizeof(*hdr));
++
++ /* find version supported by kernel */
++ memset(hdr, 0, sizeof(*hdr));
++ capget(hdr, NULL);
++
++ if (hdr->version != LINUX_CAPABILITY_VERSION_1)
+ {
+- int capsize = 1; /* for header version 1 */
+- hdr = safe_malloc(sizeof(*hdr));
+-
+- /* find version supported by kernel */
+- 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 = safe_malloc(sizeof(*data) * capsize);
+- memset(data, 0, sizeof(*data) * capsize);
++ /* if unknown version, use largest supported version (3) */
++ if (hdr->version != LINUX_CAPABILITY_VERSION_2)
++ hdr->version = LINUX_CAPABILITY_VERSION_3;
++ capsize = 2;
+ }
++
++ data = safe_malloc(sizeof(*data) * capsize);
++ capget(hdr, data); /* Get current values, for verification */
++
++ if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
++ fail = "NET_ADMIN";
++ else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
++ fail = "NET_RAW";
++ else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
++ fail = "NET_BIND_SERVICE";
++
++ if (fail)
++ die(_("process is missing required capability %s"), fail, EC_MISC);
++
++ /* Now set bitmaps to set caps after daemonising */
++ memset(data, 0, sizeof(*data) * capsize);
++
++ if (need_cap_net_admin)
++ data->effective |= (1 << CAP_NET_ADMIN);
++ if (need_cap_net_raw)
++ data->effective |= (1 << CAP_NET_RAW);
++ if (need_cap_net_bind_service)
++ data->effective |= (1 << CAP_NET_BIND_SERVICE);
++
++ data->permitted = data->effective;
+ #endif
+
+ /* Use a pipe to carry signals and other events back to the event loop
+@@ -626,18 +677,9 @@ int main (int argc, char **argv)
+ if (ent_pw && ent_pw->pw_uid != 0)
+ {
+ #if defined(HAVE_LINUX_NETWORK)
+- /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
+- CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
+- ports because of DAD, or we're doing it dynamically,
+- we need CAP_NET_BIND_SERVICE too. */
+- if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
+- data->effective = data->permitted = data->inheritable =
+- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
+- (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
+- else
+- data->effective = data->permitted = data->inheritable =
+- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
+-
++ /* Need to be able to drop root. */
++ data->effective |= (1 << CAP_SETUID);
++ data->permitted |= (1 << CAP_SETUID);
+ /* Tell kernel to not clear capabilities when dropping root */
+ if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
+ bad_capabilities = errno;
+@@ -678,15 +720,10 @@ int main (int argc, char **argv)
+ }
+
+ #ifdef HAVE_LINUX_NETWORK
+- if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
+- data->effective = data->permitted =
+- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
+- else
+- data->effective = data->permitted =
+- (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
+- data->inheritable = 0;
++ data->effective &= ~(1 << CAP_SETUID);
++ data->permitted &= ~(1 << CAP_SETUID);
+
+- /* lose the setuid and setgid capabilities */
++ /* lose the setuid capability */
+ if (capset(hdr, data) == -1)
+ {
+ send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);