43
43
/* Redefined below for Windows debug builds after important #includes */
44
44
#define _PySSL_FIX_ERRNO
45
45
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 ) { \
51
51
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 ); }
54
54
55
55
#if defined(HAVE_POLL_H )
56
56
#include <poll.h>
@@ -309,6 +309,9 @@ typedef struct {
309
309
PyObject * psk_client_callback ;
310
310
PyObject * psk_server_callback ;
311
311
#endif
312
+ /* Lock to synchronize calls when the thread state is detached.
313
+ See also gh-134698. */
314
+ PyMutex tstate_mutex ;
312
315
} PySSLContext ;
313
316
314
317
#define PySSLContext_CAST (op ) ((PySSLContext *)(op))
@@ -336,6 +339,9 @@ typedef struct {
336
339
* and shutdown methods check for chained exceptions.
337
340
*/
338
341
PyObject * exc ;
342
+ /* Lock to synchronize calls when the thread state is detached.
343
+ See also gh-134698. */
344
+ PyMutex tstate_mutex ;
339
345
} PySSLSocket ;
340
346
341
347
#define PySSLSocket_CAST (op ) ((PySSLSocket *)(op))
@@ -885,13 +891,14 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
885
891
self -> server_hostname = NULL ;
886
892
self -> err = err ;
887
893
self -> exc = NULL ;
894
+ self -> tstate_mutex = (PyMutex ){0 };
888
895
889
896
/* Make sure the SSL error state is initialized */
890
897
ERR_clear_error ();
891
898
892
- PySSL_BEGIN_ALLOW_THREADS
899
+ PySSL_BEGIN_ALLOW_THREADS ( sslctx )
893
900
self -> ssl = SSL_new (ctx );
894
- PySSL_END_ALLOW_THREADS
901
+ PySSL_END_ALLOW_THREADS ( sslctx )
895
902
if (self -> ssl == NULL) {
896
903
Py_DECREF (self );
897
904
_setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
@@ -960,12 +967,12 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
960
967
BIO_set_nbio (SSL_get_wbio (self -> ssl ), 1 );
961
968
}
962
969
963
- PySSL_BEGIN_ALLOW_THREADS
970
+ PySSL_BEGIN_ALLOW_THREADS ( self )
964
971
if (socket_type == PY_SSL_CLIENT )
965
972
SSL_set_connect_state (self - > ssl );
966
973
else
967
974
SSL_set_accept_state (self -> ssl );
968
- PySSL_END_ALLOW_THREADS
975
+ PySSL_END_ALLOW_THREADS ( self )
969
976
970
977
self -> socket_type = socket_type ;
971
978
if (sock != NULL ) {
@@ -1034,10 +1041,10 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1034
1041
/* Actually negotiate SSL connection */
1035
1042
/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
1036
1043
do {
1037
- PySSL_BEGIN_ALLOW_THREADS
1044
+ PySSL_BEGIN_ALLOW_THREADS ( self )
1038
1045
ret = SSL_do_handshake (self -> ssl );
1039
1046
err = _PySSL_errno (ret < 1 , self -> ssl , ret );
1040
- PySSL_END_ALLOW_THREADS
1047
+ PySSL_END_ALLOW_THREADS ( self )
1041
1048
self -> err = err ;
1042
1049
1043
1050
if (PyErr_CheckSignals ())
@@ -2414,9 +2421,10 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
2414
2421
ms = (int )_PyTime_AsMilliseconds (timeout , _PyTime_ROUND_CEILING );
2415
2422
assert (ms <= INT_MAX );
2416
2423
2417
- PySSL_BEGIN_ALLOW_THREADS
2424
+ Py_BEGIN_ALLOW_THREADS
2418
2425
rc = poll (& pollfd , 1 , (int )ms );
2419
- PySSL_END_ALLOW_THREADS
2426
+ Py_END_ALLOW_THREADS
2427
+ _PySSL_FIX_ERRNO ;
2420
2428
#else
2421
2429
/* Guard against socket too large for select*/
2422
2430
if (!_PyIsSelectable_fd (s -> sock_fd ))
@@ -2428,13 +2436,14 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
2428
2436
FD_SET (s -> sock_fd , & fds );
2429
2437
2430
2438
/* Wait until the socket becomes ready */
2431
- PySSL_BEGIN_ALLOW_THREADS
2439
+ Py_BEGIN_ALLOW_THREADS
2432
2440
nfds = Py_SAFE_DOWNCAST (s -> sock_fd + 1 , SOCKET_T , int );
2433
2441
if (writing )
2434
2442
rc = select (nfds , NULL , & fds , NULL , & tv );
2435
2443
else
2436
2444
rc = select (nfds , & fds , NULL , NULL , & tv );
2437
- PySSL_END_ALLOW_THREADS
2445
+ Py_END_ALLOW_THREADS
2446
+ _PySSL_FIX_ERRNO ;
2438
2447
#endif
2439
2448
2440
2449
/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
@@ -2505,10 +2514,10 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2505
2514
}
2506
2515
2507
2516
do {
2508
- PySSL_BEGIN_ALLOW_THREADS
2517
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2509
2518
retval = SSL_write_ex (self -> ssl , b -> buf , (size_t )b -> len , & count );
2510
2519
err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2511
- PySSL_END_ALLOW_THREADS
2520
+ PySSL_END_ALLOW_THREADS ( self )
2512
2521
self -> err = err ;
2513
2522
2514
2523
if (PyErr_CheckSignals ())
@@ -2566,10 +2575,10 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
2566
2575
int count = 0 ;
2567
2576
_PySSLError err ;
2568
2577
2569
- PySSL_BEGIN_ALLOW_THREADS
2578
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2570
2579
count = SSL_pending (self -> ssl );
2571
2580
err = _PySSL_errno (count < 0 , self -> ssl , count );
2572
- PySSL_END_ALLOW_THREADS
2581
+ PySSL_END_ALLOW_THREADS ( self )
2573
2582
self -> err = err ;
2574
2583
2575
2584
if (count < 0 )
@@ -2660,10 +2669,10 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
2660
2669
deadline = _PyDeadline_Init (timeout );
2661
2670
2662
2671
do {
2663
- PySSL_BEGIN_ALLOW_THREADS
2672
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2664
2673
retval = SSL_read_ex (self -> ssl , mem , (size_t )len , & count );
2665
2674
err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2666
- PySSL_END_ALLOW_THREADS
2675
+ PySSL_END_ALLOW_THREADS ( self )
2667
2676
self -> err = err ;
2668
2677
2669
2678
if (PyErr_CheckSignals ())
@@ -2762,7 +2771,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2762
2771
}
2763
2772
2764
2773
while (1 ) {
2765
- PySSL_BEGIN_ALLOW_THREADS
2774
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2766
2775
/* Disable read-ahead so that unwrap can work correctly.
2767
2776
* Otherwise OpenSSL might read in too much data,
2768
2777
* eating clear text data that happens to be
@@ -2775,7 +2784,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2775
2784
SSL_set_read_ahead (self - > ssl , 0 );
2776
2785
ret = SSL_shutdown (self -> ssl );
2777
2786
err = _PySSL_errno (ret < 0 , self -> ssl , ret );
2778
- PySSL_END_ALLOW_THREADS
2787
+ PySSL_END_ALLOW_THREADS ( self )
2779
2788
self -> err = err ;
2780
2789
2781
2790
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
@@ -3167,9 +3176,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
3167
3176
// no other thread can be touching this object yet.
3168
3177
// (Technically, we can't even lock if we wanted to, as the
3169
3178
// lock hasn't been initialized yet.)
3170
- PySSL_BEGIN_ALLOW_THREADS
3179
+ Py_BEGIN_ALLOW_THREADS
3171
3180
ctx = SSL_CTX_new (method );
3172
- PySSL_END_ALLOW_THREADS
3181
+ Py_END_ALLOW_THREADS
3182
+ _PySSL_FIX_ERRNO ;
3173
3183
3174
3184
if (ctx == NULL ) {
3175
3185
_setSSLError (get_ssl_state (module ), NULL , 0 , __FILE__ , __LINE__ );
@@ -3194,6 +3204,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
3194
3204
self -> psk_client_callback = NULL ;
3195
3205
self -> psk_server_callback = NULL ;
3196
3206
#endif
3207
+ self -> tstate_mutex = (PyMutex ){0 };
3197
3208
3198
3209
/* Don't check host name by default */
3199
3210
if (proto_version == PY_SSL_VERSION_TLS_CLIENT ) {
@@ -3312,9 +3323,10 @@ context_clear(PyObject *op)
3312
3323
Py_CLEAR (self -> psk_server_callback );
3313
3324
#endif
3314
3325
if (self -> keylog_bio != NULL ) {
3315
- PySSL_BEGIN_ALLOW_THREADS
3326
+ Py_BEGIN_ALLOW_THREADS
3316
3327
BIO_free_all (self -> keylog_bio );
3317
- PySSL_END_ALLOW_THREADS
3328
+ Py_END_ALLOW_THREADS
3329
+ _PySSL_FIX_ERRNO ;
3318
3330
self -> keylog_bio = NULL ;
3319
3331
}
3320
3332
return 0 ;
@@ -4037,7 +4049,8 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
4037
4049
_PySSLPasswordInfo * pw_info = (_PySSLPasswordInfo * ) userdata ;
4038
4050
PyObject * fn_ret = NULL ;
4039
4051
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 ;
4041
4054
4042
4055
if (pw_info -> error ) {
4043
4056
/* already failed previously. OpenSSL 3.0.0-alpha14 invokes the
@@ -4067,13 +4080,13 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
4067
4080
goto error ;
4068
4081
}
4069
4082
4070
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4083
+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
4071
4084
memcpy (buf , pw_info -> password , pw_info -> size );
4072
4085
return pw_info -> size ;
4073
4086
4074
4087
error :
4075
4088
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 );
4077
4090
pw_info -> error = 1 ;
4078
4091
return -1 ;
4079
4092
}
@@ -4126,10 +4139,10 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
4126
4139
SSL_CTX_set_default_passwd_cb (self -> ctx , _password_callback );
4127
4140
SSL_CTX_set_default_passwd_cb_userdata (self -> ctx , & pw_info );
4128
4141
}
4129
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4142
+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4130
4143
r = SSL_CTX_use_certificate_chain_file (self -> ctx ,
4131
4144
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 );
4133
4146
if (r != 1 ) {
4134
4147
if (pw_info .error ) {
4135
4148
ERR_clear_error ();
@@ -4144,11 +4157,11 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
4144
4157
}
4145
4158
goto error ;
4146
4159
}
4147
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4160
+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4148
4161
r = SSL_CTX_use_PrivateKey_file (self -> ctx ,
4149
4162
PyBytes_AS_STRING (keyfile ? keyfile_bytes : certfile_bytes ),
4150
4163
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 );
4152
4165
Py_CLEAR (keyfile_bytes );
4153
4166
Py_CLEAR (certfile_bytes );
4154
4167
if (r != 1 ) {
@@ -4165,9 +4178,9 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
4165
4178
}
4166
4179
goto error ;
4167
4180
}
4168
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4181
+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4169
4182
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 );
4171
4184
if (r != 1 ) {
4172
4185
_setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
4173
4186
goto error ;
@@ -4384,9 +4397,9 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
4384
4397
cafile_buf = PyBytes_AS_STRING (cafile_bytes );
4385
4398
if (capath )
4386
4399
capath_buf = PyBytes_AS_STRING (capath_bytes );
4387
- PySSL_BEGIN_ALLOW_THREADS
4400
+ PySSL_BEGIN_ALLOW_THREADS ( self )
4388
4401
r = SSL_CTX_load_verify_locations (self -> ctx , cafile_buf , capath_buf );
4389
- PySSL_END_ALLOW_THREADS
4402
+ PySSL_END_ALLOW_THREADS ( self )
4390
4403
if (r != 1 ) {
4391
4404
if (errno != 0 ) {
4392
4405
PyErr_SetFromErrno (PyExc_OSError );
@@ -4438,10 +4451,11 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath)
4438
4451
return NULL ;
4439
4452
4440
4453
errno = 0 ;
4441
- PySSL_BEGIN_ALLOW_THREADS
4454
+ Py_BEGIN_ALLOW_THREADS
4442
4455
dh = PEM_read_DHparams (f , NULL , NULL , NULL );
4443
4456
fclose (f );
4444
- PySSL_END_ALLOW_THREADS
4457
+ Py_END_ALLOW_THREADS
4458
+ _PySSL_FIX_ERRNO ;
4445
4459
if (dh == NULL ) {
4446
4460
if (errno != 0 ) {
4447
4461
PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , filepath );
@@ -4593,6 +4607,7 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
4593
4607
Py_BEGIN_ALLOW_THREADS
4594
4608
rc = SSL_CTX_set_default_verify_paths (self -> ctx );
4595
4609
Py_END_ALLOW_THREADS
4610
+ _PySSL_FIX_ERRNO ;
4596
4611
if (!rc ) {
4597
4612
_setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
4598
4613
return NULL ;
0 commit comments