]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix memory accounting bug in TLSDNS
authorOndřej Surý <ondrej@isc.org>
Thu, 18 Mar 2021 17:14:38 +0000 (18:14 +0100)
committerOndřej Surý <ondrej@isc.org>
Thu, 18 Mar 2021 17:14:38 +0000 (18:14 +0100)
After a partial write the tls.senddata buffer would be rearranged to
contain only the data tha wasn't sent and the len part would be made
shorter, which would lead to attempt to free only part of a socket's
tls.senddata buffer.

lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/tlsdns.c

index c558bc1f8f07c5c65cfae8abcd423316e3fcbbb9..70d4721f999cdff5652e1133a561413996c1614c 100644 (file)
@@ -806,7 +806,7 @@ struct isc_nmsocket {
                        TLS_STATE_ERROR,
                        TLS_STATE_CLOSING
                } state;
-               uv_buf_t senddata;
+               isc_region_t senddata;
                bool cycle;
                isc_result_t pending_error;
                /* List of active send requests. */
index d03bd69a8ee6241644d387cc4b22870af99175b4..cbff0f5860fba657224bffa80f3630c1ca867266 100644 (file)
@@ -1063,12 +1063,12 @@ static void
 free_senddata(isc_nmsocket_t *sock) {
        REQUIRE(VALID_NMSOCK(sock));
        REQUIRE(sock->tls.senddata.base != NULL);
-       REQUIRE(sock->tls.senddata.len > 0);
+       REQUIRE(sock->tls.senddata.length > 0);
 
        isc_mem_put(sock->mgr->mctx, sock->tls.senddata.base,
-                   sock->tls.senddata.len);
+                   sock->tls.senddata.length);
        sock->tls.senddata.base = NULL;
-       sock->tls.senddata.len = 0;
+       sock->tls.senddata.length = 0;
 }
 
 static void
@@ -1105,7 +1105,7 @@ tls_cycle_output(isc_nmsocket_t *sock) {
                int err;
 
                if (sock->tls.senddata.base != NULL ||
-                   sock->tls.senddata.len > 0) {
+                   sock->tls.senddata.length > 0) {
                        break;
                }
 
@@ -1114,42 +1114,43 @@ tls_cycle_output(isc_nmsocket_t *sock) {
                }
 
                sock->tls.senddata.base = isc_mem_get(sock->mgr->mctx, pending);
-               sock->tls.senddata.len = pending;
+               sock->tls.senddata.length = pending;
 
-               rv = BIO_read_ex(sock->tls.app_rbio, sock->tls.senddata.base,
-                                pending, &bytes);
+               req = isc__nm_uvreq_get(sock->mgr, sock);
+               req->uvbuf.base = (char *)sock->tls.senddata.base;
+               req->uvbuf.len = sock->tls.senddata.length;
+
+               rv = BIO_read_ex(sock->tls.app_rbio, req->uvbuf.base,
+                                req->uvbuf.len, &bytes);
 
                RUNTIME_CHECK(rv == 1);
                INSIST((size_t)pending == bytes);
 
-               err = uv_try_write(&sock->uv_handle.stream, &sock->tls.senddata,
-                                  1);
+               err = uv_try_write(&sock->uv_handle.stream, &req->uvbuf, 1);
 
                if (err == pending) {
                        /* Wrote everything, restart */
+                       isc__nm_uvreq_put(&req, sock);
                        free_senddata(sock);
                        continue;
                }
 
                if (err > 0) {
                        /* Partial write, send rest asynchronously */
-                       memmove(sock->tls.senddata.base,
-                               sock->tls.senddata.base + err, pending - err);
-                       sock->tls.senddata.len = pending - err;
+                       memmove(req->uvbuf.base, req->uvbuf.base + err,
+                               req->uvbuf.len - err);
+                       req->uvbuf.len = req->uvbuf.len - err;
                } else if (err == UV_ENOSYS || err == UV_EAGAIN) {
                        /* uv_try_write is not supported, send asynchronously */
                } else {
                        result = isc__nm_uverr2result(err);
+                       isc__nm_uvreq_put(&req, sock);
                        free_senddata(sock);
                        break;
                }
 
-               req = isc__nm_uvreq_get(sock->mgr, sock);
-               req->uvbuf.base = (char *)sock->tls.senddata.base;
-               req->uvbuf.len = sock->tls.senddata.len;
-
                err = uv_write(&req->uv_req.write, &sock->uv_handle.stream,
-                              &sock->tls.senddata, 1, tls_write_cb);
+                              &req->uvbuf, 1, tls_write_cb);
 
                INSIST(err == 0);