Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20260427101326.3331-1-me@ziyao.cc>
Date: Mon, 27 Apr 2026 10:13:26 +0000
From: Yao Zi <me@...ao.cc>
To: musl@...ts.openwall.com
Cc: Yao Zi <me@...ao.cc>
Subject: [PATCH v2] dns: Avoid division-by-zero when zero attempts is specified in resolv.conf

DNS query retry interval is calculated through timeout / attempts in
__res_msend_rc(), both are loaded from resolv.conf in
__get_resolv_conf(), while value of attempts isn't checked. This would
trigger an undefined behavior if attempts is set to zero in
configuration, causing misfunction or termination with SIGFPE.

Gracefully handle it by returning early.

Fixes: d6cb08bcaca4 ("factor resolv.conf parsing out of res_msend to its own file")
Signed-off-by: Yao Zi <me@...ao.cc>
---

This bug is found by auditing musl source code with Large Language
Model's help. However, LLM is only used to seek for problems, and I've
confirmed the issue by hand and reproduced it. This fix, and the commit
message are all written by myself, though I've viewed some of generated
reproducer.

Back to the technical part, this problem could be easily reproduced by
adding

	options attempts:0

to resolv.conf (do not close the editor since many stuff might
fault!), then basically every program recursively invoking
__res_msend_rc() through either gethostbyname*() or res_send() would
crash on x86_64 with SIGFPE.

It does sound weird to make zero attempt on DNS requests, but glibc
accepts so, and fails with errno = ECONNREFUSED, which seems an
unintended behavior and is undocumented, thus isn't followed in v2
of this patch.

It's worth noting that before the commit introduced this bug, musl
silently clamps attempts to be at least one, which makes sense but
introducing such an implicit behavior might be unexpected. It might also
be useful to allow falling all DNS queries intentionally through
attempts:0.

Thanks for your time and review.

Changed from v1:
- Do not set errno (the glibc behavior) when attempts is zero
- Link to v1: https://www.openwall.com/lists/musl/2026/04/18/1

 src/network/res_msend.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index 51d42ecb76f2..253ed0d1e7de 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -99,10 +99,12 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 	int r;
 	unsigned long t0, t1, t2;
 
-	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
-
 	timeout = 1000*conf->timeout;
 	attempts = conf->attempts;
+	if (!attempts)
+		return -1;
+
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
 
 	for (nns=0; nns<conf->nns; nns++) {
 		const struct address *iplit = &conf->ns[nns];
-- 
2.53.0

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.