diff --git a/SOURCES/dnsmasq-2.81-optimize-fds-close.patch b/SOURCES/dnsmasq-2.81-optimize-fds-close.patch new file mode 100644 index 0000000..58689da --- /dev/null +++ b/SOURCES/dnsmasq-2.81-optimize-fds-close.patch @@ -0,0 +1,132 @@ +commit 98c6998116e33f9f34b798682e0695f4166bd86d +Author: Simon Kelley +Date: Mon Mar 2 17:10:25 2020 +0000 + + Optimise closing file descriptors. + + Dnsmasq needs to close all the file descriptors it inherits, for security + reasons. This is traditionally done by calling close() on every possible + file descriptor (most of which won't be open.) On big servers where + "every possible file descriptor" is a rather large set, this gets + rather slow, so we use the /proc//fd directory to get a list + of the fds which are acually open. + + This only works on Linux. On other platforms, and on Linux systems + without a /proc filesystem, we fall back to the old way. + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 573aac0..10f19ea 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -138,20 +138,18 @@ int main (int argc, char **argv) + } + #endif + +- /* Close any file descriptors we inherited apart from std{in|out|err} +- +- Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist, ++ /* Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist, + otherwise file descriptors we create can end up being 0, 1, or 2 + and then get accidentally closed later when we make 0, 1, and 2 + open to /dev/null. Normally we'll be started with 0, 1 and 2 open, + but it's not guaranteed. By opening /dev/null three times, we + ensure that we're not using those fds for real stuff. */ +- for (i = 0; i < max_fd; i++) +- if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO) +- close(i); +- else +- open("/dev/null", O_RDWR); +- ++ for (i = 0; i < 3; i++) ++ open("/dev/null", O_RDWR); ++ ++ /* Close any file descriptors we inherited apart from std{in|out|err} */ ++ close_fds(max_fd, -1, -1, -1); ++ + #ifndef HAVE_LINUX_NETWORK + # if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)) + if (!option_bool(OPT_NOWILD)) +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 6103eb5..c46bfeb 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1283,7 +1283,7 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len, + int expand_buf(struct iovec *iov, size_t size); + char *print_mac(char *buff, unsigned char *mac, int len); + int read_write(int fd, unsigned char *packet, int size, int rw); +- ++void close_fds(long max_fd, int spare1, int spare2, int spare3); + int wildcard_match(const char* wildcard, const char* match); + int wildcard_matchn(const char* wildcard, const char* match, int num); + +diff --git a/src/helper.c b/src/helper.c +index 1b260a1..7072cf4 100644 +--- a/src/helper.c ++++ b/src/helper.c +@@ -131,12 +131,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) + Don't close err_fd, in case the lua-init fails. + Note that we have to do this before lua init + so we don't close any lua fds. */ +- for (max_fd--; max_fd >= 0; max_fd--) +- if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && +- max_fd != STDIN_FILENO && max_fd != pipefd[0] && +- max_fd != event_fd && max_fd != err_fd) +- close(max_fd); +- ++ close_fds(max_fd, pipefd[0], event_fd, err_fd); ++ + #ifdef HAVE_LUASCRIPT + if (daemon->luascript) + { +diff --git a/src/util.c b/src/util.c +index 73bf62a..f058c92 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -705,6 +705,47 @@ int read_write(int fd, unsigned char *packet, int size, int rw) + return 1; + } + ++/* close all fds except STDIN, STDOUT and STDERR, spare1, spare2 and spare3 */ ++void close_fds(long max_fd, int spare1, int spare2, int spare3) ++{ ++ /* On Linux, use the /proc/ filesystem to find which files ++ are actually open, rather than iterate over the whole space, ++ for efficiency reasons. If this fails we drop back to the dumb code. */ ++#ifdef HAVE_LINUX_NETWORK ++ DIR *d; ++ ++ if ((d = opendir("/proc/self/fd"))) ++ { ++ struct dirent *de; ++ ++ while ((de = readdir(d))) ++ { ++ long fd; ++ char *e = NULL; ++ ++ errno = 0; ++ fd = strtol(de->d_name, &e, 10); ++ ++ if (errno != 0 || !e || *e || fd == dirfd(d) || ++ fd == STDOUT_FILENO || fd == STDERR_FILENO || fd == STDIN_FILENO || ++ fd == spare1 || fd == spare2 || fd == spare3) ++ continue; ++ ++ close(fd); ++ } ++ ++ closedir(d); ++ return; ++ } ++#endif ++ ++ /* fallback, dumb code. */ ++ for (max_fd--; max_fd >= 0; max_fd--) ++ if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && max_fd != STDIN_FILENO && ++ max_fd != spare1 && max_fd != spare2 && max_fd != spare3) ++ close(max_fd); ++} ++ + /* Basically match a string value against a wildcard pattern. */ + int wildcard_match(const char* wildcard, const char* match) + { diff --git a/SPECS/dnsmasq.spec b/SPECS/dnsmasq.spec index b766add..061f998 100644 --- a/SPECS/dnsmasq.spec +++ b/SPECS/dnsmasq.spec @@ -13,7 +13,7 @@ Name: dnsmasq Version: 2.79 -Release: 11%{?extraversion:.%{extraversion}}%{?dist}.1 +Release: 13%{?extraversion:.%{extraversion}}%{?dist} Summary: A lightweight DHCP/caching DNS server License: GPLv2 or GPLv3 @@ -50,7 +50,8 @@ Patch17: dnsmasq-2.81-prefix-ranges-or-list-of-ipv6-addresses.patch # http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=52ec7836139e7a11374971905e5ac0d2d02e32c0 Patch18: dnsmasq-2.81-tag-filtering-of-dhcp-host-directives.patch Patch19: dnsmasq-2.81-correct-range-check-of-dhcp-host-prefix.patch -Patch20: dnsmasq-2.81-rh1829448.patch +Patch20: dnsmasq-2.81-optimize-fds-close.patch +Patch21: dnsmasq-2.81-rh1829448.patch # This is workaround to nettle bug #1549190 # https://bugzilla.redhat.com/show_bug.cgi?id=1549190 @@ -103,7 +104,8 @@ server's leases. %patch17 -p1 -b .rh1779187-2 %patch18 -p1 -b .rh1779187-3 %patch19 -p1 -b .rh1779187-4 -%patch20 -p1 -b .rh1829448 +%patch20 -p1 -b .rh1816613 +%patch21 -p1 -b .rh1829448 # use /var/lib/dnsmasq instead of /var/lib/misc for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do @@ -204,9 +206,12 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/dnsmasq.conf %{_mandir}/man1/dhcp_* %changelog -* Mon May 18 2020 Petr Menšík - 2.79-11.1 +* Tue May 05 2020 Petr Menšík - 2.79-13 - Fix mixed address family reservations on DHCP (#1829448) +* Mon Mar 30 2020 Tomas Korbar - 2.79-12 +- Minimize count of close syscalls on startup (#1816613) + * Mon Mar 02 2020 Petr Menšík - 2.79-11 - Support multiple static leases for single mac on IPv6 (#1779187)