Skip Menu |
Report information
The Basics
Id: 45547
Status: resolved
Priority: 50/50
Queue: bind9-public

Bug Information
Version Fixed: 9.12.0, 9.11.3, 9.10.7, 9.9.12
Version Found: (no value)
Versions Affected: (no value)
Versions Planned: (no value)
Priority: P3 Low
Severity: S2 Normal
CVSS Score: (no value)
CVE ID: (no value)
Component: (no value)
Area: bug

Created:Wed, 12 Jul 2017 13:43:07 -0400
Updated:Mon, 11 Sep 2017 13:39:10 -0400
Closed:Mon, 11 Sep 2017 13:39:10 -0400

This bug tracker is no longer active.

Please go to our Gitlab to submit issues (both feature requests and bug reports) for active projects maintained by Internet Systems Consortium (ISC).

Due to security and confidentiality requirements, full access is limited to the primary maintainers.

Subject: [PATCH] dig: search origin is lost in dig +tcp retry
Date: Wed, 12 Jul 2017 19:42:59 +0200
From: "Petr Menšík" <>
Download (untitled) / with headers
text/plain 1.6KiB
Hi, It came out, under specific firewall filtering, dig behaviour will be different in +tcp and +notcp mode. It was reported to me on RHEL 6 bind 9.8.2. It is present still in the latest devel beta 9.11.2b1. Easiest way to reproduce it is to use iptables to drop incoming acknowledges. # iptables -I INPUT -p udp --sport domain -j DROP # iptables -I INPUT -p tcp --sport domain --tcp-flags ACK,SYN ACK -j DROP If I use command: $ dig -d +retry=4 +tcp +domain=example foo or with "search example" in resolv.conf with $ dig -d +retry=4 +tcp +search +showsearch foo The first connection will query foo expanded by domain example. After it timeouts, it will try a new connection. New connection is created without the search list however, so only bare name is used on following retries. UDP searches are not modified, because they do not use requeue_lookup call (logs "making new TCP request"). It will send queries to foo.example at first. Queries to foo. start to appear on the new connection. You can observe used origin before each query. It is also visible in wireshark on captured data. It behaves well in UDP mode, no matter how many retries, it will still use full foo.example. name. In TCP mode, it stops using example. soon. It was reported to me because behavior was inconsistent in bug It turned out firewall was involved in private messages. Proposed fix is included. I am not sure if it is intentional to skip lookup->origin in clone_lookup. It might be useful to copy it from original lookup when servers is true. But the most simple fix is included. Regards, Petr -- Petr Menšík, Software Engineer Red Hat

Message body is not shown because sender requested not to inline it.

Download (untitled) / with headers
text/plain 1.6KiB
Hi Petr, Thank you for reporting this issue and preparing a patch. Your fix is correct, but I took a closer look at the relevant code anyway to check whether this is indeed the optimal solution. In bin/dig/dighost.c, clone_lookup() is only called from requeue_lookup(). There are currently seven call sites for the latter; five of these modify origin for the new lookup immediately after the call to requeue_lookup(), which leaves us with two: - TCP retry in connect_timeout() (the one you reported), where not reassigning the origin from the previous lookup is a bug, - queueing a follow-up lookup when +nssearch is used, where not reassigning the origin from the previous lookup is also a bug: if the user does something like "dig isc +domain=org +nssearch", SOA queries will be sent for "isc" instead of "". clone_lookup() is also used in three other source files: - bin/dig/dig.c: five calls, all used for cloning a default lookup whose origin is always NULL, so origin reassignment in clone_lookup() does not really matter here, - bin/dig/host.c: two calls, both immediately followed by assigning NULL to origin, - bin/dig/nslookup.c: one call, immediately followed by assigning NULL to origin. Given the above, I prepared a different fix which causes clone_lookup() to reassign origin from the previous lookup, so that explicit reassignments ("n->origin = query->lookup->origin;") can be removed. Any caller that wants to tweak origin after calling clone_lookup() or requeue_lookup() already does that anyway. I will shortly submit my fix for review. Thank you again for bringing this issue to our attention.
The change to dig looks fine. I might have considered a simpler for this, just a script that accepts TCP connections and then ignores them, but the way you did it is fine. I changed the test to count incidences of "trying origin bar", because the test could pass if it only appeared once (or for that matter if it appeared more than twice). If you like the change, this is okay to commit.
Michal and I discussed this last week via jabber, and except that he preferred grep/wc to awk in the test script, we agreed it was okay to merge. It doesn't seem to have happened yet, though, so I'm going to merge it so it can be in the alpha. 4712. [bug] "dig +domain" and "dig +search" didn't retain the search domain when retrying with TCP. [RT #45547] 9.12.0, 9.11.3, 9.10.7, 9.9.12