4242/* Redefined below for Windows debug builds after important #includes */
4343#define _PySSL_FIX_ERRNO
4444
45- #define PySSL_BEGIN_ALLOW_THREADS_S (save ) \
46- do { (save) = PyEval_SaveThread(); } while(0)
47- #define PySSL_END_ALLOW_THREADS_S (save ) \
48- do { PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0)
49- #define PySSL_BEGIN_ALLOW_THREADS { \
45+ #define PySSL_BEGIN_ALLOW_THREADS_S (save , mutex ) \
46+ do { (save) = PyEval_SaveThread(); PyMutex_Lock(mutex); } while(0)
47+ #define PySSL_END_ALLOW_THREADS_S (save , mutex ) \
48+ do { PyMutex_Unlock(mutex); PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0)
49+ #define PySSL_BEGIN_ALLOW_THREADS ( self ) { \
5050 PyThreadState *_save = NULL; \
51- PySSL_BEGIN_ALLOW_THREADS_S(_save);
52- #define PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS_S(_save); }
51+ PySSL_BEGIN_ALLOW_THREADS_S(_save, &self->tstate_mutex );
52+ #define PySSL_END_ALLOW_THREADS ( self ) PySSL_END_ALLOW_THREADS_S(_save, &self->tstate_mutex ); }
5353
5454#if defined(HAVE_POLL_H )
5555#include <poll.h>
@@ -304,6 +304,9 @@ typedef struct {
304304 PyObject * psk_client_callback ;
305305 PyObject * psk_server_callback ;
306306#endif
307+ /* Lock to synchronize calls when the thread state is detached.
308+ See also gh-134698. */
309+ PyMutex tstate_mutex ;
307310} PySSLContext ;
308311
309312typedef struct {
@@ -329,6 +332,9 @@ typedef struct {
329332 * and shutdown methods check for chained exceptions.
330333 */
331334 PyObject * exc ;
335+ /* Lock to synchronize calls when the thread state is detached.
336+ See also gh-134698. */
337+ PyMutex tstate_mutex ;
332338} PySSLSocket ;
333339
334340typedef struct {
@@ -840,13 +846,14 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
840846 self -> server_hostname = NULL ;
841847 self -> err = err ;
842848 self -> exc = NULL ;
849+ self -> tstate_mutex = (PyMutex ){0 };
843850
844851 /* Make sure the SSL error state is initialized */
845852 ERR_clear_error ();
846853
847- PySSL_BEGIN_ALLOW_THREADS
854+ PySSL_BEGIN_ALLOW_THREADS ( sslctx )
848855 self -> ssl = SSL_new (ctx );
849- PySSL_END_ALLOW_THREADS
856+ PySSL_END_ALLOW_THREADS ( sslctx )
850857 if (self -> ssl == NULL) {
851858 Py_DECREF (self );
852859 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
@@ -912,12 +919,12 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
912919 BIO_set_nbio (SSL_get_wbio (self -> ssl ), 1 );
913920 }
914921
915- PySSL_BEGIN_ALLOW_THREADS
922+ PySSL_BEGIN_ALLOW_THREADS ( self )
916923 if (socket_type == PY_SSL_CLIENT )
917924 SSL_set_connect_state (self - > ssl );
918925 else
919926 SSL_set_accept_state (self -> ssl );
920- PySSL_END_ALLOW_THREADS
927+ PySSL_END_ALLOW_THREADS ( self )
921928
922929 self -> socket_type = socket_type ;
923930 if (sock != NULL ) {
@@ -986,10 +993,10 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
986993 /* Actually negotiate SSL connection */
987994 /* XXX If SSL_do_handshake() returns 0, it's also a failure. */
988995 do {
989- PySSL_BEGIN_ALLOW_THREADS
996+ PySSL_BEGIN_ALLOW_THREADS ( self )
990997 ret = SSL_do_handshake (self -> ssl );
991998 err = _PySSL_errno (ret < 1 , self -> ssl , ret );
992- PySSL_END_ALLOW_THREADS
999+ PySSL_END_ALLOW_THREADS ( self )
9931000 self -> err = err ;
9941001
9951002 if (PyErr_CheckSignals ())
@@ -2362,9 +2369,10 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
23622369 ms = (int )_PyTime_AsMilliseconds (timeout , _PyTime_ROUND_CEILING );
23632370 assert (ms <= INT_MAX );
23642371
2365- PySSL_BEGIN_ALLOW_THREADS
2372+ Py_BEGIN_ALLOW_THREADS
23662373 rc = poll (& pollfd , 1 , (int )ms );
2367- PySSL_END_ALLOW_THREADS
2374+ Py_END_ALLOW_THREADS
2375+ _PySSL_FIX_ERRNO ;
23682376#else
23692377 /* Guard against socket too large for select*/
23702378 if (!_PyIsSelectable_fd (s -> sock_fd ))
@@ -2376,13 +2384,14 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
23762384 FD_SET (s -> sock_fd , & fds );
23772385
23782386 /* Wait until the socket becomes ready */
2379- PySSL_BEGIN_ALLOW_THREADS
2387+ Py_BEGIN_ALLOW_THREADS
23802388 nfds = Py_SAFE_DOWNCAST (s -> sock_fd + 1 , SOCKET_T , int );
23812389 if (writing )
23822390 rc = select (nfds , NULL , & fds , NULL , & tv );
23832391 else
23842392 rc = select (nfds , & fds , NULL , NULL , & tv );
2385- PySSL_END_ALLOW_THREADS
2393+ Py_END_ALLOW_THREADS
2394+ _PySSL_FIX_ERRNO ;
23862395#endif
23872396
23882397 /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
@@ -2453,10 +2462,10 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
24532462 }
24542463
24552464 do {
2456- PySSL_BEGIN_ALLOW_THREADS
2465+ PySSL_BEGIN_ALLOW_THREADS ( self )
24572466 retval = SSL_write_ex (self -> ssl , b -> buf , (size_t )b -> len , & count );
24582467 err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2459- PySSL_END_ALLOW_THREADS
2468+ PySSL_END_ALLOW_THREADS ( self )
24602469 self -> err = err ;
24612470
24622471 if (PyErr_CheckSignals ())
@@ -2514,10 +2523,10 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
25142523 int count = 0 ;
25152524 _PySSLError err ;
25162525
2517- PySSL_BEGIN_ALLOW_THREADS
2526+ PySSL_BEGIN_ALLOW_THREADS ( self )
25182527 count = SSL_pending (self -> ssl );
25192528 err = _PySSL_errno (count < 0 , self -> ssl , count );
2520- PySSL_END_ALLOW_THREADS
2529+ PySSL_END_ALLOW_THREADS ( self )
25212530 self -> err = err ;
25222531
25232532 if (count < 0 )
@@ -2608,10 +2617,10 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
26082617 deadline = _PyDeadline_Init (timeout );
26092618
26102619 do {
2611- PySSL_BEGIN_ALLOW_THREADS
2620+ PySSL_BEGIN_ALLOW_THREADS ( self )
26122621 retval = SSL_read_ex (self -> ssl , mem , (size_t )len , & count );
26132622 err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2614- PySSL_END_ALLOW_THREADS
2623+ PySSL_END_ALLOW_THREADS ( self )
26152624 self -> err = err ;
26162625
26172626 if (PyErr_CheckSignals ())
@@ -2710,7 +2719,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
27102719 }
27112720
27122721 while (1 ) {
2713- PySSL_BEGIN_ALLOW_THREADS
2722+ PySSL_BEGIN_ALLOW_THREADS ( self )
27142723 /* Disable read-ahead so that unwrap can work correctly.
27152724 * Otherwise OpenSSL might read in too much data,
27162725 * eating clear text data that happens to be
@@ -2723,7 +2732,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
27232732 SSL_set_read_ahead (self - > ssl , 0 );
27242733 ret = SSL_shutdown (self -> ssl );
27252734 err = _PySSL_errno (ret < 0 , self -> ssl , ret );
2726- PySSL_END_ALLOW_THREADS
2735+ PySSL_END_ALLOW_THREADS ( self )
27272736 self -> err = err ;
27282737
27292738 /* If err == 1, a secure shutdown with SSL_shutdown() is complete */
@@ -3115,9 +3124,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31153124 // no other thread can be touching this object yet.
31163125 // (Technically, we can't even lock if we wanted to, as the
31173126 // lock hasn't been initialized yet.)
3118- PySSL_BEGIN_ALLOW_THREADS
3127+ Py_BEGIN_ALLOW_THREADS
31193128 ctx = SSL_CTX_new (method );
3120- PySSL_END_ALLOW_THREADS
3129+ Py_END_ALLOW_THREADS
3130+ _PySSL_FIX_ERRNO ;
31213131
31223132 if (ctx == NULL ) {
31233133 _setSSLError (get_ssl_state (module ), NULL , 0 , __FILE__ , __LINE__ );
@@ -3143,6 +3153,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31433153 self -> psk_client_callback = NULL ;
31443154 self -> psk_server_callback = NULL ;
31453155#endif
3156+ self -> tstate_mutex = (PyMutex ){0 };
31463157
31473158 /* Don't check host name by default */
31483159 if (proto_version == PY_SSL_VERSION_TLS_CLIENT ) {
@@ -3259,9 +3270,10 @@ context_clear(PySSLContext *self)
32593270 Py_CLEAR (self -> psk_server_callback );
32603271#endif
32613272 if (self -> keylog_bio != NULL ) {
3262- PySSL_BEGIN_ALLOW_THREADS
3273+ Py_BEGIN_ALLOW_THREADS
32633274 BIO_free_all (self -> keylog_bio );
3264- PySSL_END_ALLOW_THREADS
3275+ Py_END_ALLOW_THREADS
3276+ _PySSL_FIX_ERRNO ;
32653277 self -> keylog_bio = NULL ;
32663278 }
32673279 return 0 ;
@@ -3980,7 +3992,8 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
39803992 _PySSLPasswordInfo * pw_info = (_PySSLPasswordInfo * ) userdata ;
39813993 PyObject * fn_ret = NULL ;
39823994
3983- PySSL_END_ALLOW_THREADS_S (pw_info -> thread_state );
3995+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
3996+ _PySSL_FIX_ERRNO ;
39843997
39853998 if (pw_info -> error ) {
39863999 /* already failed previously. OpenSSL 3.0.0-alpha14 invokes the
@@ -4010,13 +4023,13 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
40104023 goto error ;
40114024 }
40124025
4013- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4026+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
40144027 memcpy (buf , pw_info -> password , pw_info -> size );
40154028 return pw_info -> size ;
40164029
40174030error :
40184031 Py_XDECREF (fn_ret );
4019- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4032+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
40204033 pw_info -> error = 1 ;
40214034 return -1 ;
40224035}
@@ -4069,10 +4082,10 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
40694082 SSL_CTX_set_default_passwd_cb (self -> ctx , _password_callback );
40704083 SSL_CTX_set_default_passwd_cb_userdata (self -> ctx , & pw_info );
40714084 }
4072- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4085+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
40734086 r = SSL_CTX_use_certificate_chain_file (self -> ctx ,
40744087 PyBytes_AS_STRING (certfile_bytes ));
4075- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4088+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
40764089 if (r != 1 ) {
40774090 if (pw_info .error ) {
40784091 ERR_clear_error ();
@@ -4087,11 +4100,11 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
40874100 }
40884101 goto error ;
40894102 }
4090- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4103+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
40914104 r = SSL_CTX_use_PrivateKey_file (self -> ctx ,
40924105 PyBytes_AS_STRING (keyfile ? keyfile_bytes : certfile_bytes ),
40934106 SSL_FILETYPE_PEM );
4094- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4107+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
40954108 Py_CLEAR (keyfile_bytes );
40964109 Py_CLEAR (certfile_bytes );
40974110 if (r != 1 ) {
@@ -4108,9 +4121,9 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
41084121 }
41094122 goto error ;
41104123 }
4111- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4124+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41124125 r = SSL_CTX_check_private_key (self -> ctx );
4113- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4126+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
41144127 if (r != 1 ) {
41154128 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
41164129 goto error ;
@@ -4327,9 +4340,9 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
43274340 cafile_buf = PyBytes_AS_STRING (cafile_bytes );
43284341 if (capath )
43294342 capath_buf = PyBytes_AS_STRING (capath_bytes );
4330- PySSL_BEGIN_ALLOW_THREADS
4343+ PySSL_BEGIN_ALLOW_THREADS ( self )
43314344 r = SSL_CTX_load_verify_locations (self -> ctx , cafile_buf , capath_buf );
4332- PySSL_END_ALLOW_THREADS
4345+ PySSL_END_ALLOW_THREADS ( self )
43334346 if (r != 1 ) {
43344347 if (errno != 0 ) {
43354348 PyErr_SetFromErrno (PyExc_OSError );
@@ -4381,10 +4394,11 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath)
43814394 return NULL ;
43824395
43834396 errno = 0 ;
4384- PySSL_BEGIN_ALLOW_THREADS
4397+ Py_BEGIN_ALLOW_THREADS
43854398 dh = PEM_read_DHparams (f , NULL , NULL , NULL );
43864399 fclose (f );
4387- PySSL_END_ALLOW_THREADS
4400+ Py_END_ALLOW_THREADS
4401+ _PySSL_FIX_ERRNO ;
43884402 if (dh == NULL ) {
43894403 if (errno != 0 ) {
43904404 PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , filepath );
@@ -4536,6 +4550,7 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
45364550 Py_BEGIN_ALLOW_THREADS
45374551 rc = SSL_CTX_set_default_verify_paths (self -> ctx );
45384552 Py_END_ALLOW_THREADS
4553+ _PySSL_FIX_ERRNO ;
45394554 if (!rc ) {
45404555 _setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
45414556 return NULL ;
0 commit comments