nss: fix crash when closing HTTPS conn over HTTPS proxy
Truncated valgrind output capturing the crash follows: Invalid read of size 8 at 0x628B4A0: PR_Close (priometh.c:104) by 0x43C088: nss_close (nss.c:1356) by 0x43C17F: Curl_nss_close (nss.c:1377) by 0x438F42: Curl_ssl_close (vtls.c:618) by 0x45460B: Curl_disconnect (url.c:3000) by 0x42EACA: close_all_connections (multi.c:1887) by 0x42EB37: curl_multi_cleanup (multi.c:1907) by 0x44B4CA: Curl_close (url.c:427) by 0x4282C2: curl_easy_cleanup (easy.c:859) by 0x41341C: main_free (tool_main.c:206) by 0x4134F4: main (tool_main.c:260) Address 0x99afa10 is 0 bytes inside a block of size 48 free'd at 0x4C29D6A: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) by 0x62A2C33: pt_Close (ptio.c:1277) by 0x43BACD: nspr_io_close (nss.c:1141) by 0x54D6E25: ssl_DefClose (ssldef.c:203) by 0x43BACD: nspr_io_close (nss.c:1141) by 0x54D6E25: ssl_DefClose (ssldef.c:203) by 0x43C088: nss_close (nss.c:1356) by 0x43C173: Curl_nss_close (nss.c:1376) by 0x438F42: Curl_ssl_close (vtls.c:618) by 0x45460B: Curl_disconnect (url.c:3000) by 0x42EACA: close_all_connections (multi.c:1887) by 0x42EB37: curl_multi_cleanup (multi.c:1907) Block was alloc'd at at 0x4C28C50: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) by 0x6289F71: _PR_Getfd (prfdcach.c:103) by 0x62A4816: pt_SetMethods.isra.13 (ptio.c:3303) by 0x62A56E5: PR_ImportTCPSocket (ptio.c:4577) by 0x43D4D0: nss_setup_connect (nss.c:1733) by 0x43DDCA: nss_connect_common (nss.c:1929) by 0x43DF1E: Curl_nss_connect_nonblocking (nss.c:1985) by 0x4386CE: Curl_ssl_connect_nonblocking (vtls.c:364) by 0x47F02C: https_proxy_connect (http_proxy.c:58) by 0x47F086: Curl_proxy_connect (http_proxy.c:74) by 0x445891: Curl_http_connect (http.c:1348) by 0x42D613: multi_runsingle (multi.c:1233)
This commit is contained in:
@@ -1338,21 +1338,26 @@ Curl_nss_check_cxn(struct connectdata *conn)
|
|||||||
|
|
||||||
static void nss_close(struct ssl_connect_data *connssl)
|
static void nss_close(struct ssl_connect_data *connssl)
|
||||||
{
|
{
|
||||||
|
/* before the cleanup, check whether we are using a client certificate */
|
||||||
|
const bool client_cert = (connssl->client_nickname != NULL)
|
||||||
|
|| (connssl->obj_clicert != NULL);
|
||||||
|
|
||||||
|
free(connssl->client_nickname);
|
||||||
|
connssl->client_nickname = NULL;
|
||||||
|
|
||||||
|
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
|
||||||
|
Curl_llist_destroy(connssl->obj_list, NULL);
|
||||||
|
connssl->obj_list = NULL;
|
||||||
|
connssl->obj_clicert = NULL;
|
||||||
|
|
||||||
if(connssl->handle) {
|
if(connssl->handle) {
|
||||||
if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
|
if(client_cert)
|
||||||
/* A server might require different authentication based on the
|
/* A server might require different authentication based on the
|
||||||
* particular path being requested by the client. To support this
|
* particular path being requested by the client. To support this
|
||||||
* scenario, we must ensure that a connection will never reuse the
|
* scenario, we must ensure that a connection will never reuse the
|
||||||
* authentication data from a previous connection. */
|
* authentication data from a previous connection. */
|
||||||
SSL_InvalidateSession(connssl->handle);
|
SSL_InvalidateSession(connssl->handle);
|
||||||
|
|
||||||
free(connssl->client_nickname);
|
|
||||||
connssl->client_nickname = NULL;
|
|
||||||
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
|
|
||||||
Curl_llist_destroy(connssl->obj_list, NULL);
|
|
||||||
connssl->obj_list = NULL;
|
|
||||||
connssl->obj_clicert = NULL;
|
|
||||||
|
|
||||||
PR_Close(connssl->handle);
|
PR_Close(connssl->handle);
|
||||||
connssl->handle = NULL;
|
connssl->handle = NULL;
|
||||||
}
|
}
|
||||||
@@ -1373,6 +1378,11 @@ void Curl_nss_close(struct connectdata *conn, int sockindex)
|
|||||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(connssl->handle)
|
||||||
|
/* nss_close(connssl) will transitively close also connssl_proxy->handle
|
||||||
|
if both are used. Clear it to avoid a double close leading to crash. */
|
||||||
|
connssl_proxy->handle = NULL;
|
||||||
|
|
||||||
nss_close(connssl);
|
nss_close(connssl);
|
||||||
nss_close(connssl_proxy);
|
nss_close(connssl_proxy);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user