Double free on shutdown after binding a TLS socket fails
With no root privileges and the following named.conf
:
options {
listen-on tls ephemeral { 127.0.0.1; };
};
I can see this message logged during startup:
07-Oct-2021 08:08:46.020 creating TLS socket: permission denied
and then this one during shutdown:
corrupted size vs. prev_size while consolidating
Aborted (core dumped)
(The message logged by libc may vary across hosts.)
The bug lies here:
501 static isc_result_t
502 ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
503 isc_result_t result;
504
505 result = isc_nm_listentlsdns(
506 ifp->mgr->nm, &ifp->addr, ns__client_request, ifp,
507 ns__client_tcpconn, ifp, sizeof(ns_client_t), ifp->mgr->backlog,
508 &ifp->mgr->sctx->tcpquota, sslctx, &ifp->tcplistensocket);
509
510 if (result != ISC_R_SUCCESS) {
511 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
512 "creating TLS socket: %s",
513 isc_result_totext(result));
514 >>> isc_tlsctx_free(&sslctx);
515 return (result);
516 }
The isc_tlsctx_free()
call on line 514 cleans up the isc_tlsctx_t
passed to ns_interface_listentls()
, but look how the latter is called:
627 if (elt->sslctx != NULL) {
628 result = ns_interface_listentls(ifp, elt->sslctx);
629 if (result != ISC_R_SUCCESS) {
630 goto cleanup_interface;
631 }
632 *ifpret = ifp;
633 return (result);
634 }
Specifically, note that elt->sslctx
is passed by value, so even if
ns_interface_listentls()
releases the SSL context, elt->sslctx
remains non-NULL. This makes ns_listenelt_destroy()
call
isc_tlsctx_free()
again for an already destroyed SSL context.
This bug has been around for at least the past 8 months, so there is no rush to fix it in October.