]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Add guards to avoid race condition on TCP connection
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 7 Jan 2022 14:12:05 +0000 (14:12 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 7 Jan 2022 14:12:05 +0000 (14:12 +0000)
contrib/librdns/dns_private.h
contrib/librdns/resolver.c
contrib/librdns/util.c

index adb753fd464dfd957b5903b653d04268b15d49fc..c240debea29929a9462cf74bf08eccafc271ac8b 100644 (file)
@@ -142,6 +142,7 @@ enum rdns_io_channel_flags {
        RDNS_CHANNEL_CONNECTED = 1u << 0u,
        RDNS_CHANNEL_ACTIVE = 1u << 1u,
        RDNS_CHANNEL_TCP = 1u << 2u,
+       RDNS_CHANNEL_TCP_CONNECTING = 1u << 3u,
 };
 
 #define IS_CHANNEL_CONNECTED(ioc) (((ioc)->flags & RDNS_CHANNEL_CONNECTED) != 0)
index cd6a8f97d6dfd92cc792a9b179df0c947a829eeb..9f5ca9872f910d76613c749c85c3aa8d5b162064 100644 (file)
@@ -431,6 +431,7 @@ static void
 rdns_process_tcp_connect (int fd, struct rdns_io_channel *ioc)
 {
        ioc->flags |= RDNS_CHANNEL_CONNECTED|RDNS_CHANNEL_ACTIVE;
+       ioc->flags &= ~RDNS_CHANNEL_TCP_CONNECTING;
 
        if (ioc->tcp->async_read == NULL) {
                ioc->tcp->async_read = ioc->resolver->async->add_read(ioc->resolver->async->data,
index 1ff8b18581c1e77f42de994d6095a25784c49321..0f5533d5304246b84fef65564d2e48b1f3815308 100644 (file)
@@ -730,6 +730,12 @@ rdns_ioc_tcp_connect (struct rdns_io_channel *ioc)
                return false;
        }
 
+       if (ioc->flags & RDNS_CHANNEL_TCP_CONNECTING) {
+               /* Already connecting channel, ignore connect request */
+
+               return true;
+       }
+
        if (ioc->sock == -1) {
                ioc->sock = rdns_make_client_socket (ioc->srv->name, ioc->srv->port,
                                SOCK_STREAM, &ioc->saddr, &ioc->slen);
@@ -765,13 +771,21 @@ rdns_ioc_tcp_connect (struct rdns_io_channel *ioc)
                }
                else {
                        /* We need to wait for write readiness here */
-                       ioc->tcp->async_write = resolver->async->add_write (resolver->async->data,
-                                       ioc->sock, ioc);
+                       if (ioc->tcp->async_write != NULL) {
+                               rdns_err("internal rdns error: write event is already registered on connect");
+                       }
+                       else {
+                               ioc->tcp->async_write = resolver->async->add_write(resolver->async->data,
+                                               ioc->sock, ioc);
+                       }
+                       /* Prevent double connect attempts */
+                       ioc->flags |= RDNS_CHANNEL_TCP_CONNECTING;
                }
        }
        else {
                /* Always be ready to read from a TCP socket */
                ioc->flags |= RDNS_CHANNEL_CONNECTED|RDNS_CHANNEL_ACTIVE;
+               ioc->flags &= ~RDNS_CHANNEL_TCP_CONNECTING;
                ioc->tcp->async_read = resolver->async->add_read(resolver->async->data,
                                ioc->sock, ioc);
        }