2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

Add system test lingering CLOSE_WAIT TCP sockets

Add a test case to check for lingering TCP sockets stuck in the
CLOSE_WAIT state. This can happen if a client sends some garbage after
its first query.

The system test runs the reproducer script and then sends another TCP
query to the resolver. The resolver is configured to allow one TCP
client only. If BIND has its TCP socket stuck in CLOSE_WAIT, it does
not have the resources available to answer the second query.

Note: A better test would be to check if the named daemon does not
have a TCP socket stuck in CLOSE_WAIT for example with netstat. When
running this test locally you can examine named with netstat manually.
But since netstat is platform specific it is not a good candidate to do
this as a system test.

If you, if you could return, don't let it burn.
Do you have to let it linger?
- Cranberries
This commit is contained in:
Matthijs Mekking 2022-02-03 10:49:25 +01:00 committed by Michal Nowak
parent 180f77dd9c
commit b9ebde705b
No known key found for this signature in database
GPG Key ID: 24A3E8463AEE5E56
2 changed files with 36 additions and 3 deletions

View File

@ -0,0 +1 @@
dropedns

View File

@ -27,9 +27,8 @@ import dns.query
TIMEOUT = 10
def create_msg(qname, qtype):
msg = dns.message.make_query(qname, qtype, want_dnssec=True,
use_edns=0, payload=4096)
def create_msg(qname, qtype, edns=-1):
msg = dns.message.make_query(qname, qtype, use_edns=edns)
return msg
@ -87,3 +86,36 @@ def test_tcp_garbage_response(named_port):
(response, rtime) = dns.query.receive_tcp(sock, timeout())
except ConnectionError as e:
raise EOFError from e
# Regression test for CVE-2022-0396
def test_close_wait(named_port):
with create_socket("10.53.0.7", named_port) as sock:
msg = create_msg("a.example.", "A")
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
(response, rtime) = dns.query.receive_tcp(sock, timeout())
msg = dns.message.make_query("a.example.", "A", use_edns=0,
payload=1232)
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
# Shutdown the socket, but ignore the other side closing the socket
# first because we sent DNS message with EDNS0
try:
sock.shutdown(socket.SHUT_RDWR)
except ConnectionError:
pass
except OSError:
pass
# BIND allows one TCP client, the part above sends DNS messaage with EDNS0
# after the first query. BIND should react adequately because of
# ns7/named.dropedns and close the socket, making room for the next
# request. If it gets stuck in CLOSE_WAIT state, there is no connection
# available for the query below and it will time out.
with create_socket("10.53.0.7", named_port) as sock:
msg = create_msg("a.example.", "A")
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
(response, rtime) = dns.query.receive_tcp(sock, timeout())