-
-
Notifications
You must be signed in to change notification settings - Fork 33.9k
gh-143756: Fix potential data race in SSLContext.load_cert_chain #143818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Concurrent calls to `load_cert_chain` caused data races in OpenSSL code.
picnixz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need tests for that actually?
| do { (save) = PyEval_SaveThread(); } while(0) | ||
| #define PySSL_END_ALLOW_THREADS_S(save) \ | ||
| do { PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0) | ||
| #define PySSL_BEGIN_ALLOW_THREADS(self) { \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you are it, can you use a do-while construct? (here we would just have the do {) In addition can you make it multiline with line continuations aligned on a tab multiple? (like PEP-7) TiA.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
| do { (save) = PyEval_SaveThread(); PyMutex_Lock(mutex); } while(0) | ||
| #define PySSL_END_ALLOW_THREADS_S(save, mutex) \ | ||
| do { PyMutex_Unlock(mutex); PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0) | ||
| #define PySSL_BEGIN_ALLOW_THREADS_S(save) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use uppercase letters for the macro parameters please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not do a bunch of extra refactoring in a bugfix PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right you want to backport this. I think there will be anyway conflicts so yeah let's not make it more complicate
| if (keyfile == Py_None) | ||
| keyfile = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be added in the if (keyfile) check instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto; this is existing code
| if (password != Py_None) { | ||
| if (PyCallable_Check(password)) { | ||
| pw_info.callable = password; | ||
| } else if (!_pwinfo_set(&pw_info, password, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } else if (!_pwinfo_set(&pw_info, password, | |
| } | |
| else if (!_pwinfo_set(&pw_info, password, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
| if (PyCallable_Check(password)) { | ||
| pw_info.callable = password; | ||
| } else if (!_pwinfo_set(&pw_info, password, | ||
| "password should be a string or callable")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And realign this adter putting the elseif on its own line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
| if (!PyUnicode_FSConverter(certfile, &certfile_bytes)) { | ||
| if (PyErr_ExceptionMatches(PyExc_TypeError)) { | ||
| PyErr_SetString(PyExc_TypeError, | ||
| "certfile should be a valid filesystem path"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a follow-up: This is a bit misleading. For me such message usually implies a ValueError instead of TypeError. Do we use this formulation for other occurrences of FSConverter?
Maybe: "expecting a path-like object for 'certfile', got ..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
|
Tests already exist. #143752 runs it with TSan |
picnixz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry as I was on mobile I didn't see that it was just moving code around. We can refactor this later (I really want to split ssl.c because it is messy to maintain but it is also annoying to create more files...)
Concurrent calls to
load_cert_chaincaused data races in OpenSSL code.