Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250224210446.50198-1-musl@roblab.la>
Date: Mon, 24 Feb 2025 22:04:46 +0100
From: roblabla <musl@...lab.la>
To: musl@...ts.openwall.com
Cc: roblabla <musl@...lab.la>
Subject: [PATCH] resolvconf: Set minimum timeout value to 1

/etc/resolv.conf has an option to configure the timeout, in seconds,
that the DNS resolution must wait before considering that resolution to
have failed. While there is no documentation about what happens when
that value contains a 0 or negative value, some machines appear to have
it configured this way.

Previously, when resolv.conf contained a timeout value of 0, musl would
fail to do any DNS resolution. More precisely, __res_msend_rc wouldn't
even try to send a single query out, as the bulk of the work is done in
a loop that checks for timeout expiration. With the timeout set to 0,
we wouldn't even enter this loop, and thus never send a single DNS
request. This would manifest in user programs as API such as getaddrinfo
returning a TRY_AGAIN error in h_errno.

Other language runtimes seem more foolproof against this kind of
misconfiguration, mostly by considering a 0 or negative timeout value to
simply mean 1. For example:

- In glibc, we can see the timeout is automatically increased to 1 in
  the function responsible for handling this timeout:
  https://github.com/bminor/glibc/blob/glibc-2.41/resolv/res_send.c#L945-L949
- In go, when parsing the resolv.conf file, it sets the timeout value to
  1 if it was lower than that:
  https://github.com/golang/go/blob/go1.24.0/src/net/dnsconfig_unix.go#L89-L91

This commit makes musl take this approach. Upon parsing the timeout
value, if it encounters a value below or equal to 0, it simply raises it
back to 1 second. This allows MUSL program to run on machines that are
misconfigured in this way, matching the behavior of both glibc and go.
---
 src/network/resolvconf.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/network/resolvconf.c b/src/network/resolvconf.c
index ceabf080..5735165a 100644
--- a/src/network/resolvconf.c
+++ b/src/network/resolvconf.c
@@ -55,7 +55,15 @@ int __get_resolv_conf(struct resolvconf *conf, char *search, size_t search_sz)
 			if (p && (isdigit(p[8]) || p[8]=='.')) {
 				p += 8;
 				unsigned long x = strtoul(p, &z, 10);
-				if (z != p) conf->timeout = x > 60 ? 60 : x;
+				if (z != p) {
+					/* Setting a timeout to 0 would result in a non-functional
+					 * DNS resolution. Both glibc and go default to 1 when x is
+					 * set to 0, let's follow suit.
+					 */
+					if (x < 1) x = 1;
+					if (x > 60) x = 60;
+					conf->timeout = x;
+				}
 			}
 			continue;
 		}

base-commit: 1880359b54ff7dd9f5016002bfdae4b136007dde
-- 
2.47.2

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.