From 31c521b0470e57125ffcd0f1b0c6edf3b9af96c1 Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Wed, 1 Jun 2016 09:30:03 +0200 Subject: vtls: fix ssl session cache race condition Sessionid cache management is inseparable from managing individual session lifetimes. E.g. for reference-counted sessions (like those in SChannel and OpenSSL engines) every session addition and removal should be accompanied with refcount increment and decrement respectively. Failing to do so synchronously leads to a race condition that causes symptoms like use-after-free and memory corruption. This commit: - makes existing session cache locking explicit, thus allowing individual engines to manage lock's scope. - fixes OpenSSL and SChannel engines by putting refcount management inside this lock's scope in relevant places. - adds these explicit locking calls to other engines that use sessionid cache to accommodate for this change. Note, however, that it is unknown whether any of these engines could also have this race. Bug: https://github.com/curl/curl/issues/815 Fixes #815 Closes #847 --- lib/vtls/polarssl.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/vtls/polarssl.c') diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c index 0e8b0f500..14a098b39 100644 --- a/lib/vtls/polarssl.c +++ b/lib/vtls/polarssl.c @@ -337,8 +337,10 @@ polarssl_connect_step1(struct connectdata *conn, net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); + Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { ret = ssl_set_session(&connssl->ssl, old_session); + Curl_ssl_sessionid_unlock(conn); if(ret) { failf(data, "ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; @@ -572,10 +574,12 @@ polarssl_connect_step3(struct connectdata *conn, } /* If there's already a matching session in the cache, delete it */ + Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)) Curl_ssl_delsessionid(conn, old_ssl_sessionid); retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0); + Curl_ssl_sessionid_unlock(conn); if(retcode) { free(our_ssl_sessionid); failf(data, "failed to store ssl session"); -- cgit v1.2.3