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))
@@ -889,9 +892,9 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
889892 /* Make sure the SSL error state is initialized */
890893 ERR_clear_error ();
891894
892- PySSL_BEGIN_ALLOW_THREADS
895+ PySSL_BEGIN_ALLOW_THREADS ( sslctx )
893896 self -> ssl = SSL_new (ctx );
894- PySSL_END_ALLOW_THREADS
897+ PySSL_END_ALLOW_THREADS ( sslctx )
895898 if (self -> ssl == NULL) {
896899 Py_DECREF (self );
897900 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
@@ -960,12 +963,12 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
960963 BIO_set_nbio (SSL_get_wbio (self -> ssl ), 1 );
961964 }
962965
963- PySSL_BEGIN_ALLOW_THREADS
966+ Py_BEGIN_ALLOW_THREADS ;
964967 if (socket_type == PY_SSL_CLIENT )
965968 SSL_set_connect_state (self -> ssl );
966969 else
967970 SSL_set_accept_state (self -> ssl );
968- PySSL_END_ALLOW_THREADS
971+ Py_END_ALLOW_THREADS ;
969972
970973 self -> socket_type = socket_type ;
971974 if (sock != NULL ) {
@@ -1034,10 +1037,11 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
10341037 /* Actually negotiate SSL connection */
10351038 /* XXX If SSL_do_handshake() returns 0, it's also a failure. */
10361039 do {
1037- PySSL_BEGIN_ALLOW_THREADS
1040+ Py_BEGIN_ALLOW_THREADS
10381041 ret = SSL_do_handshake (self -> ssl );
10391042 err = _PySSL_errno (ret < 1 , self -> ssl , ret );
1040- PySSL_END_ALLOW_THREADS
1043+ Py_END_ALLOW_THREADS ;
1044+ _PySSL_FIX_ERRNO ;
10411045 self -> err = err ;
10421046
10431047 if (PyErr_CheckSignals ())
@@ -2414,9 +2418,10 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
24142418 ms = (int )_PyTime_AsMilliseconds (timeout , _PyTime_ROUND_CEILING );
24152419 assert (ms <= INT_MAX );
24162420
2417- PySSL_BEGIN_ALLOW_THREADS
2421+ Py_BEGIN_ALLOW_THREADS
24182422 rc = poll (& pollfd , 1 , (int )ms );
2419- PySSL_END_ALLOW_THREADS
2423+ Py_END_ALLOW_THREADS
2424+ _PySSL_FIX_ERRNO ;
24202425#else
24212426 /* Guard against socket too large for select*/
24222427 if (!_PyIsSelectable_fd (s -> sock_fd ))
@@ -2428,13 +2433,14 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
24282433 FD_SET (s -> sock_fd , & fds );
24292434
24302435 /* Wait until the socket becomes ready */
2431- PySSL_BEGIN_ALLOW_THREADS
2436+ Py_BEGIN_ALLOW_THREADS
24322437 nfds = Py_SAFE_DOWNCAST (s -> sock_fd + 1 , SOCKET_T , int );
24332438 if (writing )
24342439 rc = select (nfds , NULL , & fds , NULL , & tv );
24352440 else
24362441 rc = select (nfds , & fds , NULL , NULL , & tv );
2437- PySSL_END_ALLOW_THREADS
2442+ Py_END_ALLOW_THREADS
2443+ _PySSL_FIX_ERRNO ;
24382444#endif
24392445
24402446 /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
@@ -2505,10 +2511,11 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
25052511 }
25062512
25072513 do {
2508- PySSL_BEGIN_ALLOW_THREADS
2514+ Py_BEGIN_ALLOW_THREADS ;
25092515 retval = SSL_write_ex (self -> ssl , b -> buf , (size_t )b -> len , & count );
25102516 err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2511- PySSL_END_ALLOW_THREADS
2517+ Py_END_ALLOW_THREADS ;
2518+ _PySSL_FIX_ERRNO ;
25122519 self -> err = err ;
25132520
25142521 if (PyErr_CheckSignals ())
@@ -2566,10 +2573,11 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
25662573 int count = 0 ;
25672574 _PySSLError err ;
25682575
2569- PySSL_BEGIN_ALLOW_THREADS
2576+ Py_BEGIN_ALLOW_THREADS ;
25702577 count = SSL_pending (self -> ssl );
25712578 err = _PySSL_errno (count < 0 , self -> ssl , count );
2572- PySSL_END_ALLOW_THREADS
2579+ Py_END_ALLOW_THREADS ;
2580+ _PySSL_FIX_ERRNO ;
25732581 self -> err = err ;
25742582
25752583 if (count < 0 )
@@ -2660,10 +2668,11 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
26602668 deadline = _PyDeadline_Init (timeout );
26612669
26622670 do {
2663- PySSL_BEGIN_ALLOW_THREADS
2671+ Py_BEGIN_ALLOW_THREADS ;
26642672 retval = SSL_read_ex (self -> ssl , mem , (size_t )len , & count );
26652673 err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2666- PySSL_END_ALLOW_THREADS
2674+ Py_END_ALLOW_THREADS ;
2675+ _PySSL_FIX_ERRNO ;
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+ Py_BEGIN_ALLOW_THREADS ;
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,8 @@ _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+ Py_END_ALLOW_THREADS ;
2788+ _PySSL_FIX_ERRNO ;
27792789 self -> err = err ;
27802790
27812791 /* If err == 1, a secure shutdown with SSL_shutdown() is complete */
@@ -3167,9 +3177,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31673177 // no other thread can be touching this object yet.
31683178 // (Technically, we can't even lock if we wanted to, as the
31693179 // lock hasn't been initialized yet.)
3170- PySSL_BEGIN_ALLOW_THREADS
3180+ Py_BEGIN_ALLOW_THREADS
31713181 ctx = SSL_CTX_new (method );
3172- PySSL_END_ALLOW_THREADS
3182+ Py_END_ALLOW_THREADS
3183+ _PySSL_FIX_ERRNO ;
31733184
31743185 if (ctx == NULL ) {
31753186 _setSSLError (get_ssl_state (module ), NULL , 0 , __FILE__ , __LINE__ );
@@ -3194,6 +3205,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31943205 self -> psk_client_callback = NULL ;
31953206 self -> psk_server_callback = NULL ;
31963207#endif
3208+ self -> tstate_mutex = (PyMutex ){0 };
31973209
31983210 /* Don't check host name by default */
31993211 if (proto_version == PY_SSL_VERSION_TLS_CLIENT ) {
@@ -3312,9 +3324,10 @@ context_clear(PyObject *op)
33123324 Py_CLEAR (self -> psk_server_callback );
33133325#endif
33143326 if (self -> keylog_bio != NULL ) {
3315- PySSL_BEGIN_ALLOW_THREADS
3327+ Py_BEGIN_ALLOW_THREADS
33163328 BIO_free_all (self -> keylog_bio );
3317- PySSL_END_ALLOW_THREADS
3329+ Py_END_ALLOW_THREADS
3330+ _PySSL_FIX_ERRNO ;
33183331 self -> keylog_bio = NULL ;
33193332 }
33203333 return 0 ;
@@ -4037,7 +4050,8 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
40374050 _PySSLPasswordInfo * pw_info = (_PySSLPasswordInfo * ) userdata ;
40384051 PyObject * fn_ret = NULL ;
40394052
4040- PySSL_END_ALLOW_THREADS_S (pw_info -> thread_state );
4053+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
4054+ _PySSL_FIX_ERRNO ;
40414055
40424056 if (pw_info -> error ) {
40434057 /* already failed previously. OpenSSL 3.0.0-alpha14 invokes the
@@ -4067,13 +4081,13 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
40674081 goto error ;
40684082 }
40694083
4070- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4084+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
40714085 memcpy (buf , pw_info -> password , pw_info -> size );
40724086 return pw_info -> size ;
40734087
40744088error :
40754089 Py_XDECREF (fn_ret );
4076- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4090+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
40774091 pw_info -> error = 1 ;
40784092 return -1 ;
40794093}
@@ -4126,10 +4140,10 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41264140 SSL_CTX_set_default_passwd_cb (self -> ctx , _password_callback );
41274141 SSL_CTX_set_default_passwd_cb_userdata (self -> ctx , & pw_info );
41284142 }
4129- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4143+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41304144 r = SSL_CTX_use_certificate_chain_file (self -> ctx ,
41314145 PyBytes_AS_STRING (certfile_bytes ));
4132- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4146+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41334147 if (r != 1 ) {
41344148 if (pw_info .error ) {
41354149 ERR_clear_error ();
@@ -4144,11 +4158,11 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41444158 }
41454159 goto error ;
41464160 }
4147- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4161+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41484162 r = SSL_CTX_use_PrivateKey_file (self -> ctx ,
41494163 PyBytes_AS_STRING (keyfile ? keyfile_bytes : certfile_bytes ),
41504164 SSL_FILETYPE_PEM );
4151- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4165+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41524166 Py_CLEAR (keyfile_bytes );
41534167 Py_CLEAR (certfile_bytes );
41544168 if (r != 1 ) {
@@ -4165,9 +4179,9 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41654179 }
41664180 goto error ;
41674181 }
4168- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4182+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41694183 r = SSL_CTX_check_private_key (self -> ctx );
4170- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4184+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41714185 if (r != 1 ) {
41724186 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
41734187 goto error ;
@@ -4384,9 +4398,9 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
43844398 cafile_buf = PyBytes_AS_STRING (cafile_bytes );
43854399 if (capath )
43864400 capath_buf = PyBytes_AS_STRING (capath_bytes );
4387- PySSL_BEGIN_ALLOW_THREADS
4401+ PySSL_BEGIN_ALLOW_THREADS ( self )
43884402 r = SSL_CTX_load_verify_locations (self -> ctx , cafile_buf , capath_buf );
4389- PySSL_END_ALLOW_THREADS
4403+ PySSL_END_ALLOW_THREADS ( self )
43904404 if (r != 1 ) {
43914405 if (errno != 0 ) {
43924406 PyErr_SetFromErrno (PyExc_OSError );
@@ -4438,10 +4452,11 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath)
44384452 return NULL ;
44394453
44404454 errno = 0 ;
4441- PySSL_BEGIN_ALLOW_THREADS
4455+ Py_BEGIN_ALLOW_THREADS
44424456 dh = PEM_read_DHparams (f , NULL , NULL , NULL );
44434457 fclose (f );
4444- PySSL_END_ALLOW_THREADS
4458+ Py_END_ALLOW_THREADS
4459+ _PySSL_FIX_ERRNO ;
44454460 if (dh == NULL ) {
44464461 if (errno != 0 ) {
44474462 PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , filepath );
@@ -4593,6 +4608,7 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
45934608 Py_BEGIN_ALLOW_THREADS
45944609 rc = SSL_CTX_set_default_verify_paths (self -> ctx );
45954610 Py_END_ALLOW_THREADS
4611+ _PySSL_FIX_ERRNO ;
45964612 if (!rc ) {
45974613 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
45984614 return NULL ;
0 commit comments