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>
@@ -336,6 +336,9 @@ typedef struct {
336
336
PyObject * psk_client_callback ;
337
337
PyObject * psk_server_callback ;
338
338
#endif
339
+ /* Lock to synchronize calls when the thread state is detached.
340
+ See also gh-134698. */
341
+ PyMutex tstate_mutex ;
339
342
} PySSLContext ;
340
343
341
344
#define PySSLContext_CAST (op ) ((PySSLContext *)(op))
@@ -363,6 +366,9 @@ typedef struct {
363
366
* and shutdown methods check for chained exceptions.
364
367
*/
365
368
PyObject * exc ;
369
+ /* Lock to synchronize calls when the thread state is detached.
370
+ See also gh-134698. */
371
+ PyMutex tstate_mutex ;
366
372
} PySSLSocket ;
367
373
368
374
#define PySSLSocket_CAST (op ) ((PySSLSocket *)(op))
@@ -912,13 +918,14 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
912
918
self -> server_hostname = NULL ;
913
919
self -> err = err ;
914
920
self -> exc = NULL ;
921
+ self -> tstate_mutex = (PyMutex ){0 };
915
922
916
923
/* Make sure the SSL error state is initialized */
917
924
ERR_clear_error ();
918
925
919
- PySSL_BEGIN_ALLOW_THREADS
926
+ PySSL_BEGIN_ALLOW_THREADS ( sslctx )
920
927
self -> ssl = SSL_new (ctx );
921
- PySSL_END_ALLOW_THREADS
928
+ PySSL_END_ALLOW_THREADS ( sslctx )
922
929
if (self -> ssl == NULL) {
923
930
Py_DECREF (self );
924
931
_setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
@@ -987,12 +994,12 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
987
994
BIO_set_nbio (SSL_get_wbio (self -> ssl ), 1 );
988
995
}
989
996
990
- PySSL_BEGIN_ALLOW_THREADS
997
+ PySSL_BEGIN_ALLOW_THREADS ( self )
991
998
if (socket_type == PY_SSL_CLIENT )
992
999
SSL_set_connect_state (self - > ssl );
993
1000
else
994
1001
SSL_set_accept_state (self -> ssl );
995
- PySSL_END_ALLOW_THREADS
1002
+ PySSL_END_ALLOW_THREADS ( self )
996
1003
997
1004
self -> socket_type = socket_type ;
998
1005
if (sock != NULL ) {
@@ -1061,10 +1068,10 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1061
1068
/* Actually negotiate SSL connection */
1062
1069
/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
1063
1070
do {
1064
- PySSL_BEGIN_ALLOW_THREADS
1071
+ PySSL_BEGIN_ALLOW_THREADS ( self )
1065
1072
ret = SSL_do_handshake (self -> ssl );
1066
1073
err = _PySSL_errno (ret < 1 , self -> ssl , ret );
1067
- PySSL_END_ALLOW_THREADS
1074
+ PySSL_END_ALLOW_THREADS ( self )
1068
1075
self -> err = err ;
1069
1076
1070
1077
if (PyErr_CheckSignals ())
@@ -2441,9 +2448,10 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
2441
2448
ms = (int )_PyTime_AsMilliseconds (timeout , _PyTime_ROUND_CEILING );
2442
2449
assert (ms <= INT_MAX );
2443
2450
2444
- PySSL_BEGIN_ALLOW_THREADS
2451
+ Py_BEGIN_ALLOW_THREADS
2445
2452
rc = poll (& pollfd , 1 , (int )ms );
2446
- PySSL_END_ALLOW_THREADS
2453
+ Py_END_ALLOW_THREADS
2454
+ _PySSL_FIX_ERRNO ;
2447
2455
#else
2448
2456
/* Guard against socket too large for select*/
2449
2457
if (!_PyIsSelectable_fd (s -> sock_fd ))
@@ -2455,13 +2463,14 @@ PySSL_select(PySocketSockObject *s, int writing, PyTime_t timeout)
2455
2463
FD_SET (s -> sock_fd , & fds );
2456
2464
2457
2465
/* Wait until the socket becomes ready */
2458
- PySSL_BEGIN_ALLOW_THREADS
2466
+ Py_BEGIN_ALLOW_THREADS
2459
2467
nfds = Py_SAFE_DOWNCAST (s -> sock_fd + 1 , SOCKET_T , int );
2460
2468
if (writing )
2461
2469
rc = select (nfds , NULL , & fds , NULL , & tv );
2462
2470
else
2463
2471
rc = select (nfds , & fds , NULL , NULL , & tv );
2464
- PySSL_END_ALLOW_THREADS
2472
+ Py_END_ALLOW_THREADS
2473
+ _PySSL_FIX_ERRNO ;
2465
2474
#endif
2466
2475
2467
2476
/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
@@ -2579,10 +2588,10 @@ _ssl__SSLSocket_sendfile_impl(PySSLSocket *self, int fd, Py_off_t offset,
2579
2588
}
2580
2589
2581
2590
do {
2582
- PySSL_BEGIN_ALLOW_THREADS
2591
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2583
2592
retval = SSL_sendfile (self -> ssl , fd , (off_t )offset , size , flags );
2584
2593
err = _PySSL_errno (retval < 0 , self -> ssl , (int )retval );
2585
- PySSL_END_ALLOW_THREADS
2594
+ PySSL_END_ALLOW_THREADS ( self )
2586
2595
self -> err = err ;
2587
2596
2588
2597
if (PyErr_CheckSignals ()) {
@@ -2710,10 +2719,10 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2710
2719
}
2711
2720
2712
2721
do {
2713
- PySSL_BEGIN_ALLOW_THREADS
2722
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2714
2723
retval = SSL_write_ex (self -> ssl , b -> buf , (size_t )b -> len , & count );
2715
2724
err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2716
- PySSL_END_ALLOW_THREADS
2725
+ PySSL_END_ALLOW_THREADS ( self )
2717
2726
self -> err = err ;
2718
2727
2719
2728
if (PyErr_CheckSignals ())
@@ -2771,10 +2780,10 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
2771
2780
int count = 0 ;
2772
2781
_PySSLError err ;
2773
2782
2774
- PySSL_BEGIN_ALLOW_THREADS
2783
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2775
2784
count = SSL_pending (self -> ssl );
2776
2785
err = _PySSL_errno (count < 0 , self -> ssl , count );
2777
- PySSL_END_ALLOW_THREADS
2786
+ PySSL_END_ALLOW_THREADS ( self )
2778
2787
self -> err = err ;
2779
2788
2780
2789
if (count < 0 )
@@ -2865,10 +2874,10 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len,
2865
2874
deadline = _PyDeadline_Init (timeout );
2866
2875
2867
2876
do {
2868
- PySSL_BEGIN_ALLOW_THREADS
2877
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2869
2878
retval = SSL_read_ex (self -> ssl , mem , (size_t )len , & count );
2870
2879
err = _PySSL_errno (retval == 0 , self -> ssl , retval );
2871
- PySSL_END_ALLOW_THREADS
2880
+ PySSL_END_ALLOW_THREADS ( self )
2872
2881
self -> err = err ;
2873
2882
2874
2883
if (PyErr_CheckSignals ())
@@ -2967,7 +2976,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2967
2976
}
2968
2977
2969
2978
while (1 ) {
2970
- PySSL_BEGIN_ALLOW_THREADS
2979
+ PySSL_BEGIN_ALLOW_THREADS ( self )
2971
2980
/* Disable read-ahead so that unwrap can work correctly.
2972
2981
* Otherwise OpenSSL might read in too much data,
2973
2982
* eating clear text data that happens to be
@@ -2980,7 +2989,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2980
2989
SSL_set_read_ahead (self - > ssl , 0 );
2981
2990
ret = SSL_shutdown (self -> ssl );
2982
2991
err = _PySSL_errno (ret < 0 , self -> ssl , ret );
2983
- PySSL_END_ALLOW_THREADS
2992
+ PySSL_END_ALLOW_THREADS ( self )
2984
2993
self -> err = err ;
2985
2994
2986
2995
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
@@ -3375,9 +3384,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
3375
3384
// no other thread can be touching this object yet.
3376
3385
// (Technically, we can't even lock if we wanted to, as the
3377
3386
// lock hasn't been initialized yet.)
3378
- PySSL_BEGIN_ALLOW_THREADS
3387
+ Py_BEGIN_ALLOW_THREADS
3379
3388
ctx = SSL_CTX_new (method );
3380
- PySSL_END_ALLOW_THREADS
3389
+ Py_END_ALLOW_THREADS
3390
+ _PySSL_FIX_ERRNO ;
3381
3391
3382
3392
if (ctx == NULL ) {
3383
3393
_setSSLError (get_ssl_state (module ), NULL , 0 , __FILE__ , __LINE__ );
@@ -3402,6 +3412,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
3402
3412
self -> psk_client_callback = NULL ;
3403
3413
self -> psk_server_callback = NULL ;
3404
3414
#endif
3415
+ self -> tstate_mutex = (PyMutex ){0 };
3405
3416
3406
3417
/* Don't check host name by default */
3407
3418
if (proto_version == PY_SSL_VERSION_TLS_CLIENT ) {
@@ -3520,9 +3531,10 @@ context_clear(PyObject *op)
3520
3531
Py_CLEAR (self -> psk_server_callback );
3521
3532
#endif
3522
3533
if (self -> keylog_bio != NULL ) {
3523
- PySSL_BEGIN_ALLOW_THREADS
3534
+ Py_BEGIN_ALLOW_THREADS
3524
3535
BIO_free_all (self -> keylog_bio );
3525
- PySSL_END_ALLOW_THREADS
3536
+ Py_END_ALLOW_THREADS
3537
+ _PySSL_FIX_ERRNO ;
3526
3538
self -> keylog_bio = NULL ;
3527
3539
}
3528
3540
return 0 ;
@@ -4245,7 +4257,8 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
4245
4257
_PySSLPasswordInfo * pw_info = (_PySSLPasswordInfo * ) userdata ;
4246
4258
PyObject * fn_ret = NULL ;
4247
4259
4248
- PySSL_END_ALLOW_THREADS_S (pw_info -> thread_state );
4260
+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
4261
+ _PySSL_FIX_ERRNO ;
4249
4262
4250
4263
if (pw_info -> error ) {
4251
4264
/* already failed previously. OpenSSL 3.0.0-alpha14 invokes the
@@ -4275,13 +4288,13 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
4275
4288
goto error ;
4276
4289
}
4277
4290
4278
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4291
+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
4279
4292
memcpy (buf , pw_info -> password , pw_info -> size );
4280
4293
return pw_info -> size ;
4281
4294
4282
4295
error :
4283
4296
Py_XDECREF (fn_ret );
4284
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info -> thread_state );
4297
+ pw_info -> thread_state = PyThreadState_Swap (pw_info -> thread_state );
4285
4298
pw_info -> error = 1 ;
4286
4299
return -1 ;
4287
4300
}
@@ -4334,10 +4347,10 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
4334
4347
SSL_CTX_set_default_passwd_cb (self -> ctx , _password_callback );
4335
4348
SSL_CTX_set_default_passwd_cb_userdata (self -> ctx , & pw_info );
4336
4349
}
4337
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4350
+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4338
4351
r = SSL_CTX_use_certificate_chain_file (self -> ctx ,
4339
4352
PyBytes_AS_STRING (certfile_bytes ));
4340
- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4353
+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4341
4354
if (r != 1 ) {
4342
4355
if (pw_info .error ) {
4343
4356
ERR_clear_error ();
@@ -4352,11 +4365,11 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
4352
4365
}
4353
4366
goto error ;
4354
4367
}
4355
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4368
+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4356
4369
r = SSL_CTX_use_PrivateKey_file (self -> ctx ,
4357
4370
PyBytes_AS_STRING (keyfile ? keyfile_bytes : certfile_bytes ),
4358
4371
SSL_FILETYPE_PEM );
4359
- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4372
+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4360
4373
Py_CLEAR (keyfile_bytes );
4361
4374
Py_CLEAR (certfile_bytes );
4362
4375
if (r != 1 ) {
@@ -4373,9 +4386,9 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
4373
4386
}
4374
4387
goto error ;
4375
4388
}
4376
- PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
4389
+ PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4377
4390
r = SSL_CTX_check_private_key (self -> ctx );
4378
- PySSL_END_ALLOW_THREADS_S (pw_info .thread_state );
4391
+ PySSL_END_ALLOW_THREADS_S (pw_info .thread_state , & self -> tstate_mutex );
4379
4392
if (r != 1 ) {
4380
4393
_setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
4381
4394
goto error ;
@@ -4592,9 +4605,9 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
4592
4605
cafile_buf = PyBytes_AS_STRING (cafile_bytes );
4593
4606
if (capath )
4594
4607
capath_buf = PyBytes_AS_STRING (capath_bytes );
4595
- PySSL_BEGIN_ALLOW_THREADS
4608
+ PySSL_BEGIN_ALLOW_THREADS ( self )
4596
4609
r = SSL_CTX_load_verify_locations (self -> ctx , cafile_buf , capath_buf );
4597
- PySSL_END_ALLOW_THREADS
4610
+ PySSL_END_ALLOW_THREADS ( self )
4598
4611
if (r != 1 ) {
4599
4612
if (errno != 0 ) {
4600
4613
PyErr_SetFromErrno (PyExc_OSError );
@@ -4646,10 +4659,11 @@ _ssl__SSLContext_load_dh_params_impl(PySSLContext *self, PyObject *filepath)
4646
4659
return NULL ;
4647
4660
4648
4661
errno = 0 ;
4649
- PySSL_BEGIN_ALLOW_THREADS
4662
+ Py_BEGIN_ALLOW_THREADS
4650
4663
dh = PEM_read_DHparams (f , NULL , NULL , NULL );
4651
4664
fclose (f );
4652
- PySSL_END_ALLOW_THREADS
4665
+ Py_END_ALLOW_THREADS
4666
+ _PySSL_FIX_ERRNO ;
4653
4667
if (dh == NULL ) {
4654
4668
if (errno != 0 ) {
4655
4669
PyErr_SetFromErrnoWithFilenameObject (PyExc_OSError , filepath );
@@ -4801,6 +4815,7 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self)
4801
4815
Py_BEGIN_ALLOW_THREADS
4802
4816
rc = SSL_CTX_set_default_verify_paths (self -> ctx );
4803
4817
Py_END_ALLOW_THREADS
4818
+ _PySSL_FIX_ERRNO ;
4804
4819
if (!rc ) {
4805
4820
_setSSLError (get_state_ctx (self ), NULL , 0 , __FILE__ , __LINE__ );
4806
4821
return NULL ;
0 commit comments