4343/* Redefined below for Windows debug builds after important #includes */
4444#define _PySSL_FIX_ERRNO
4545
46- #define PySSL_BEGIN_ALLOW_THREADS_S (save ) \
47- do { (save) = PyEval_SaveThread(); } while(0)
48- #define PySSL_END_ALLOW_THREADS_S (save ) \
49- do { PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0)
50- #define PySSL_BEGIN_ALLOW_THREADS { \
46+ #define PySSL_BEGIN_ALLOW_THREADS_S (save , mutex ) \
47+ do { (save) = PyEval_SaveThread(); PyMutex_Lock(mutex); } while(0)
48+ #define PySSL_END_ALLOW_THREADS_S (save , mutex ) \
49+ do { PyMutex_Unlock(mutex); PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0)
50+ #define PySSL_BEGIN_ALLOW_THREADS ( self ) { \
5151 PyThreadState *_save = NULL; \
52- PySSL_BEGIN_ALLOW_THREADS_S(_save);
53- #define PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS_S(_save); }
52+ PySSL_BEGIN_ALLOW_THREADS_S(_save, &self->tstate_mutex );
53+ #define PySSL_END_ALLOW_THREADS ( self ) PySSL_END_ALLOW_THREADS_S(_save, &self->tstate_mutex ); }
5454
5555#if defined(HAVE_POLL_H )
5656#include <poll.h>
@@ -309,6 +309,9 @@ typedef struct {
309309 PyObject * psk_client_callback ;
310310 PyObject * psk_server_callback ;
311311#endif
312+ /* Lock to synchronize calls when the thread state is detached.
313+ See also gh-134698. */
314+ PyMutex tstate_mutex ;
312315} PySSLContext ;
313316
314317#define PySSLContext_CAST (op ) ((PySSLContext *)(op))
@@ -336,6 +339,9 @@ typedef struct {
336339 * and shutdown methods check for chained exceptions.
337340 */
338341 PyObject * exc ;
342+ /* Lock to synchronize calls when the thread state is detached.
343+ See also gh-134698. */
344+ PyMutex tstate_mutex ;
339345} PySSLSocket ;
340346
341347#define PySSLSocket_CAST (op ) ((PySSLSocket *)(op))
@@ -885,13 +891,14 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
885891 self -> server_hostname = NULL ;
886892 self -> err = err ;
887893 self -> exc = NULL ;
894+ self -> tstate_mutex = (PyMutex ){0 };
888895
889896 /* Make sure the SSL error state is initialized */
890897 ERR_clear_error ();
891898
892- PySSL_BEGIN_ALLOW_THREADS
899+ PySSL_BEGIN_ALLOW_THREADS ( sslctx )
893900 self -> ssl = SSL_new (ctx );
894- PySSL_END_ALLOW_THREADS
901+ PySSL_END_ALLOW_THREADS ( sslctx )
895902 if (self -> ssl == NULL) {
896903 Py_DECREF (self );
897904 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
@@ -960,12 +967,12 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
960967 BIO_set_nbio (SSL_get_wbio (self -> ssl ), 1 );
961968 }
962969
963- PySSL_BEGIN_ALLOW_THREADS
970+ PySSL_BEGIN_ALLOW_THREADS ( self )
964971 if (socket_type == PY_SSL_CLIENT )
965972 SSL_set_connect_state (self - > ssl );
966973 else
967974 SSL_set_accept_state (self -> ssl );
968- PySSL_END_ALLOW_THREADS
975+ PySSL_END_ALLOW_THREADS ( self )
969976
970977 self -> socket_type = socket_type ;
971978 if (sock != NULL ) {
@@ -1034,10 +1041,10 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
10341041 /* Actually negotiate SSL connection */
10351042 /* XXX If SSL_do_handshake() returns 0, it's also a failure. */
10361043 do {
1037- PySSL_BEGIN_ALLOW_THREADS
1044+ PySSL_BEGIN_ALLOW_THREADS ( self )
10381045 ret = SSL_do_handshake (self -> ssl );
10391046 err = _PySSL_errno (ret < 1 , self -> ssl , ret );
1040- PySSL_END_ALLOW_THREADS
1047+ PySSL_END_ALLOW_THREADS ( self )
10411048 self -> err = err ;
10421049
10431050 if (PyErr_CheckSignals ())
@@ -2414,9 +2421,10 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
24142421 ms = (int )_PyTime_AsMilliseconds (timeout , _PyTime_ROUND_CEILING );
24152422 assert (ms <= INT_MAX );
24162423
2417- PySSL_BEGIN_ALLOW_THREADS
2424+ Py_BEGIN_ALLOW_THREADS
24182425 rc = poll (& pollfd , 1 , (int )ms );
2419- PySSL_END_ALLOW_THREADS
2426+ Py_END_ALLOW_THREADS
2427+ _PySSL_FIX_ERRNO ;
24202428#else
24212429 /* Guard against socket too large for select*/
24222430 if (!_PyIsSelectable_fd (s -> sock_fd ))
@@ -2428,13 +2436,14 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
24282436 FD_SET (s -> sock_fd , & fds );
24292437
24302438 /* Wait until the socket becomes ready */
2431- PySSL_BEGIN_ALLOW_THREADS
2439+ Py_BEGIN_ALLOW_THREADS
24322440 nfds = Py_SAFE_DOWNCAST (s -> sock_fd + 1 , SOCKET_T , int );
24332441 if (writing )
24342442 rc = select (nfds , NULL , & fds , NULL , & tv );
24352443 else
24362444 rc = select (nfds , & fds , NULL , NULL , & tv );
2437- PySSL_END_ALLOW_THREADS
2445+ Py_END_ALLOW_THREADS
2446+ _PySSL_FIX_ERRNO ;
24382447#endif
24392448
24402449 /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
@@ -2505,10 +2514,10 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
25052514 }
25062515
25072516 do {
2508- PySSL_BEGIN_ALLOW_THREADS
2517+ PySSL_BEGIN_ALLOW_THREADS ( self )
25092518 retval = SSL_write_ex (self -> ssl , b -> buf , (size_t )b -> len , & count );
25102519 err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2511- PySSL_END_ALLOW_THREADS
2520+ PySSL_END_ALLOW_THREADS ( self )
25122521 self -> err = err ;
25132522
25142523 if (PyErr_CheckSignals ())
@@ -2566,10 +2575,10 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
25662575 int count = 0 ;
25672576 _PySSLError err ;
25682577
2569- PySSL_BEGIN_ALLOW_THREADS
2578+ PySSL_BEGIN_ALLOW_THREADS ( self )
25702579 count = SSL_pending (self -> ssl );
25712580 err = _PySSL_errno (count < 0 , self -> ssl , count );
2572- PySSL_END_ALLOW_THREADS
2581+ PySSL_END_ALLOW_THREADS ( self )
25732582 self -> err = err ;
25742583
25752584 if (count < 0 )
@@ -2660,10 +2669,10 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
26602669 deadline = _PyDeadline_Init (timeout );
26612670
26622671 do {
2663- PySSL_BEGIN_ALLOW_THREADS
2672+ PySSL_BEGIN_ALLOW_THREADS ( self )
26642673 retval = SSL_read_ex (self -> ssl , mem , (size_t )len , & count );
26652674 err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2666- PySSL_END_ALLOW_THREADS
2675+ PySSL_END_ALLOW_THREADS ( self )
26672676 self -> err = err ;
26682677
26692678 if (PyErr_CheckSignals ())
@@ -2762,7 +2771,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
27622771 }
27632772
27642773 while (1 ) {
2765- PySSL_BEGIN_ALLOW_THREADS
2774+ PySSL_BEGIN_ALLOW_THREADS ( self )
27662775 /* Disable read-ahead so that unwrap can work correctly.
27672776 * Otherwise OpenSSL might read in too much data,
27682777 * eating clear text data that happens to be
@@ -2775,7 +2784,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
27752784 SSL_set_read_ahead (self - > ssl , 0 );
27762785 ret = SSL_shutdown (self -> ssl );
27772786 err = _PySSL_errno (ret < 0 , self -> ssl , ret );
2778- PySSL_END_ALLOW_THREADS
2787+ PySSL_END_ALLOW_THREADS ( self )
27792788 self -> err = err ;
27802789
27812790 /* If err == 1, a secure shutdown with SSL_shutdown() is complete */
@@ -3167,9 +3176,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31673176 // no other thread can be touching this object yet.
31683177 // (Technically, we can't even lock if we wanted to, as the
31693178 // lock hasn't been initialized yet.)
3170- PySSL_BEGIN_ALLOW_THREADS
3179+ Py_BEGIN_ALLOW_THREADS
31713180 ctx = SSL_CTX_new (method );
3172- PySSL_END_ALLOW_THREADS
3181+ Py_END_ALLOW_THREADS
3182+ _PySSL_FIX_ERRNO ;
31733183
31743184 if (ctx == NULL ) {
31753185 _setSSLError (get_ssl_state (module ), NULL , 0 , __FILE__ , __LINE__ );
@@ -3194,6 +3204,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31943204 self -> psk_client_callback = NULL ;
31953205 self -> psk_server_callback = NULL ;
31963206#endif
3207+ self -> tstate_mutex = (PyMutex ){0 };
31973208
31983209 /* Don't check host name by default */
31993210 if (proto_version == PY_SSL_VERSION_TLS_CLIENT ) {
@@ -3312,9 +3323,10 @@ context_clear(PyObject *op)
33123323 Py_CLEAR (self -> psk_server_callback );
33133324#endif
33143325 if (self -> keylog_bio != NULL ) {
3315- PySSL_BEGIN_ALLOW_THREADS
3326+ Py_BEGIN_ALLOW_THREADS
33163327 BIO_free_all (self -> keylog_bio );
3317- PySSL_END_ALLOW_THREADS
3328+ Py_END_ALLOW_THREADS
3329+ _PySSL_FIX_ERRNO ;
33183330 self -> keylog_bio = NULL ;
33193331 }
33203332 return 0 ;
@@ -4037,7 +4049,8 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
40374049 _PySSLPasswordInfo * pw_info = (_PySSLPasswordInfo * ) userdata ;
40384050 PyObject * fn_ret = NULL ;
40394051
4040- PySSL_END_ALLOW_THREADS_S (pw_info -> thread_state );
4052+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
4053+ _PySSL_FIX_ERRNO ;
40414054
40424055 if (pw_info -> error ) {
40434056 /* already failed previously. OpenSSL 3.0.0-alpha14 invokes the
@@ -4067,13 +4080,13 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
40674080 goto error ;
40684081 }
40694082
4070- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4083+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
40714084 memcpy (buf , pw_info -> password , pw_info -> size );
40724085 return pw_info -> size ;
40734086
40744087error :
40754088 Py_XDECREF (fn_ret );
4076- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4089+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
40774090 pw_info -> error = 1 ;
40784091 return -1 ;
40794092}
@@ -4126,10 +4139,10 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41264139 SSL_CTX_set_default_passwd_cb (self -> ctx , _password_callback );
41274140 SSL_CTX_set_default_passwd_cb_userdata (self -> ctx , & pw_info );
41284141 }
4129- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4142+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41304143 r = SSL_CTX_use_certificate_chain_file (self -> ctx ,
41314144 PyBytes_AS_STRING (certfile_bytes ));
4132- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4145+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41334146 if (r != 1 ) {
41344147 if (pw_info .error ) {
41354148 ERR_clear_error ();
@@ -4144,11 +4157,11 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41444157 }
41454158 goto error ;
41464159 }
4147- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4160+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41484161 r = SSL_CTX_use_PrivateKey_file (self -> ctx ,
41494162 PyBytes_AS_STRING (keyfile ? keyfile_bytes : certfile_bytes ),
41504163 SSL_FILETYPE_PEM );
4151- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4164+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41524165 Py_CLEAR (keyfile_bytes );
41534166 Py_CLEAR (certfile_bytes );
41544167 if (r != 1 ) {
@@ -4165,9 +4178,9 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41654178 }
41664179 goto error ;
41674180 }
4168- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4181+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41694182 r = SSL_CTX_check_private_key (self -> ctx );
4170- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4183+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41714184 if (r != 1 ) {
41724185 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
41734186 goto error ;
@@ -4384,9 +4397,9 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
43844397 cafile_buf = PyBytes_AS_STRING (cafile_bytes );
43854398 if (capath )
43864399 capath_buf = PyBytes_AS_STRING (capath_bytes );
4387- PySSL_BEGIN_ALLOW_THREADS
4400+ PySSL_BEGIN_ALLOW_THREADS ( self )
43884401 r = SSL_CTX_load_verify_locations (self -> ctx , cafile_buf , capath_buf );
4389- PySSL_END_ALLOW_THREADS
4402+ PySSL_END_ALLOW_THREADS ( self )
43904403 if (r != 1 ) {
43914404 if (errno != 0 ) {
43924405 PyErr_SetFromErrno (PyExc_OSError );
@@ -4438,10 +4451,11 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath)
44384451 return NULL ;
44394452
44404453 errno = 0 ;
4441- PySSL_BEGIN_ALLOW_THREADS
4454+ Py_BEGIN_ALLOW_THREADS
44424455 dh = PEM_read_DHparams (f , NULL , NULL , NULL );
44434456 fclose (f );
4444- PySSL_END_ALLOW_THREADS
4457+ Py_END_ALLOW_THREADS
4458+ _PySSL_FIX_ERRNO ;
44454459 if (dh == NULL ) {
44464460 if (errno != 0 ) {
44474461 PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , filepath );
@@ -4593,6 +4607,7 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
45934607 Py_BEGIN_ALLOW_THREADS
45944608 rc = SSL_CTX_set_default_verify_paths (self -> ctx );
45954609 Py_END_ALLOW_THREADS
4610+ _PySSL_FIX_ERRNO ;
45964611 if (!rc ) {
45974612 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
45984613 return NULL ;
0 commit comments