From 7b390a7fb6ca10b60147b72acec0e951da251a7d Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Wed, 17 Jan 2024 15:40:56 +0200 Subject: [PATCH] Fix reading extra messages in TLS DNS in client mode When connecting to a remote party the TLS DNS code could process more than one message at a time despite the fact that it is expected that we should stop after every DNS message. Every DNS message is handled and consumed from the input buffer by isc__nm_process_sock_buffer(). However, as opposed to TCP DNS code, it can be called more than once when processing incoming data from a server (see tls_cycle_input()). That, in turn means that we can process more than one message at a time. Some higher level code might not expect that, as it breaks the contract. In particular, in the original report that happened during isc__nm_async_tlsdnsshutdown() call: when shutting down multiple calls to tls_cycle() are possible (each possibly leading to a isc__nm_process_sock_buffer()). If there are any non processed messages left, for any of the messages left the read callback will be called even when it is not expected as there were no preceding isc_nm_read(). To keep TCP DNS and TLS DNS code in sync, we make a similar change to it as well, although it should not matter. --- lib/isc/netmgr/tcpdns.c | 7 +++++++ lib/isc/netmgr/tlsdns.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index eda6aa62ce..cabc90533d 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -808,6 +808,13 @@ isc__nm_tcpdns_processbuffer(isc_nmsocket_t *sock) { return (ISC_R_CANCELED); } + if (sock->client && !sock->recv_read) { + /* + * We are not reading data - stop here. + */ + return (ISC_R_CANCELED); + } + req = isc__nm_get_read_req(sock, NULL); REQUIRE(VALID_UVREQ(req)); diff --git a/lib/isc/netmgr/tlsdns.c b/lib/isc/netmgr/tlsdns.c index d30e33fbfd..cfc62eb5e9 100644 --- a/lib/isc/netmgr/tlsdns.c +++ b/lib/isc/netmgr/tlsdns.c @@ -1016,6 +1016,13 @@ isc__nm_tlsdns_processbuffer(isc_nmsocket_t *sock) { return (ISC_R_CANCELED); } + if (sock->client && !sock->recv_read) { + /* + * We are not reading data - stop here. + */ + return (ISC_R_CANCELED); + } + req = isc__nm_get_read_req(sock, NULL); REQUIRE(VALID_UVREQ(req));