-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
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
Clear OpenSSL error queue after SSL_shutdown #11736
Conversation
It sounds reasonable but it is unfortunate that the docs for If I want to reproduce the problem to also verify the fix, do you have any advice? |
Hiiii @bagder! 👋
They seem to say something about it on the manpage (or am I mistaken?):
Source: https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html
We observed the problem when libcurl executed and then we got the error seemingly raised in our code. We managed to find out that it was raised by libcurl by patching OpenSSL to include a stack trace whenever it raised an error: If you want to reproduce it, you may try adding some errors to the OpenSSL queue and then call ✨ ✨ ✨ |
That talks about when not to call SSL_shutdown, it says nothing about adding data to or leaving lingering entries in the error queue. Are you saying libcurl might be calling I'm only asking to educate myself. I can't imagine that it can be bad to clear the error queue there and since you have done this research I believe this helps. |
Just found a reproduction using curl's test suite, thanks for prompting, I'll document it below. As for docs (which agreed could be better), from
Following that through to
So anything using OpenSSL's API, which may cause an error, may add things to the thread-local error queue. It's definitely an unfortunate API, but it's how almost all OpenSSL methods work. I suppose there's some ambiguity over whether the queue should be cleared before any operation (which was added to curl in a0dd9df, but not all libraries do this) or after (which generally libraries do just by virtue of handling errors, I think it should be a requirement). Here's a reproduction: With that if we run test 405 we can see the "shutdown while in init" error:
So this probably indicates that |
Clearing error states is not our responsibility. For example we don't guarantee errno is 0 after libcurl returns. Anyhow I think your request is fine. It should be changed to a one-liner, the comments are unnecessary. |
We've seen errors left in the OpenSSL error queue (specifically, "shutdown while in init") by adding some logging it revealed that the source was this file. Since we call SSL_read and SSL_shutdown here, but don't check the return code for an error, we should clear the OpenSSL error queue in case one was raised. This didn't affect curl because we call ERR_clear_error before every write operation (a0dd9df), but when libcurl is used in a process with other OpenSSL users, they may detect an OpenSSL error pushed by libcurl's SSL_shutdown as if it was their own. Co-authored-by: Satana de Sant'Ana <[email protected]>
aad0b2d
to
46b0edd
Compare
I'd argue if we want to coexist with other OpenSSL unfortunately does not work this way: you must check Again, no argument from me that that this is in any way a good API, but if you want to use OpenSSL in a shared environment, clearing the error queue is necessary.
Great 🙇♂️! I've force-pushed with the comment removed. |
I disagree. That's not a hack. See here: SSL_get_error() must be used in the same thread that performed the TLS/SSL I/O operation, and no other OpenSSL function calls should appear in between. The current thread's error queue must be empty before the TLS/SSL I/O operation is attempted, or SSL_get_error() will not work reliably. The only way to ensure that is clear the queue before the call. |
I agree with @jay that, exactly as this PR proves, it seems overly fragile for OpenSSL users to rely on all other users do clear the queue. The only reasonable action is for everyone to make sure it is cleared for their own use. Like the errno comparison. I will still merge this because it seems clears things up and does not hurt. |
Thanks! |
We've seen errors left in the OpenSSL error queue (specifically, "shutdown while in init") by adding some logging it revealed that the source was this file. Since we call SSL_read and SSL_shutdown here, but don't check the return code for an error, we should clear the OpenSSL error queue in case one was raised. This didn't affect curl because we call ERR_clear_error before every write operation (a0dd9df), but when libcurl is used in a process with other OpenSSL users, they may detect an OpenSSL error pushed by libcurl's SSL_shutdown as if it was their own. Co-authored-by: Satana de Sant'Ana <[email protected]> Closes curl#11736
In production we've observed from other libraries errors left in the OpenSSL error queue (specifically, "shutdown while in init"). By adding some logging to the errors being pushed it revealed that the source was this file.
Since we call
SSL_read
andSSL_shutdown
here, but don't check the return code for an error, we should clear the OpenSSL error queue in case one was raised.This didn't affect curl because we call ERR_clear_error before every write operation (a0dd9df), but when libcurl is used in a process with other OpenSSL users, they may detect an OpenSSL error pushed by libcurl's
SSL_shutdown
as if it was their own.Our use of libcurl is through
ethon
, a Ruby wrapper, so I'm not 100% sure the use of libcurl is correct, but this does seem like a place we must clear errors, since we don't handle them.