rustls: only return CURLE_AGAIN when TLS session is fully drained#6894
Closed
jblazquez wants to merge 1 commit intocurl:masterfrom
Closed
rustls: only return CURLE_AGAIN when TLS session is fully drained#6894jblazquez wants to merge 1 commit intocurl:masterfrom
jblazquez wants to merge 1 commit intocurl:masterfrom
Conversation
The code in cr_recv was returning prematurely as soon as the socket reported no more data to read. However, this could be leaving some unread plaintext data in the rustls session from a previous call, causing causing the transfer to hang if the socket never receives further data. We need to ensure that the session is fully drained of plaintext data before returning CURLE_AGAIN to the caller.
6374c26 to
3733ec4
Compare
Member
|
/cc @jsha |
jsha
approved these changes
Apr 15, 2021
Contributor
jsha
left a comment
There was a problem hiding this comment.
Thanks for the patch, and the detailed breakdown of the issue @jblazquez. I agree with your assessment of the bug, and the patch looks good to me.
bagder
approved these changes
Apr 15, 2021
Member
|
Thanks, both of you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The code in cr_recv was returning prematurely as soon as the socket reported no more data to read. However, this could be leaving some unread plaintext data in the rustls session from a previous call, causing the transfer to hang if the socket never receives further data. We need to ensure that the session is fully drained of plaintext data before returning CURLE_AGAIN to the caller.
To illustrate the problem, consider the following sequence of events as an example:
cr_recvis called andsreadreturns 15KB of TLS data.rustls_client_session_read_tlsis passed the 15KB of data and stores it.rustls_client_session_process_new_packetsis called but since the first TLS record isn't complete it does nothing.rustls_client_session_readreturns EOF because there is no plaintext data to read yet.cr_recvreturnsCURLE_AGAINcr_recvis called andsreadreturns 9KB of TLS data.rustls_client_session_read_tlsis passed the 9KB of data and stores it.rustls_client_session_process_new_packetsis called, and since both TLS records are complete, it processes them and extracts the 20KB of plaintext data.rustls_client_session_readreturns 16KB of plaintext, because that's the size of theplainbufpassed tocr_recv.cr_recvreturns 16KB.cr_recvis called again andsreadreturns EAGAIN since there are no more TCP segments to read.cr_recvreturnsCURLE_AGAINprematurely, even though there are still 4KB of plaintext to be read from the session.I don't have an easy repro for you, but the problem manifests very frequently in our internal application. These are the corresponding curl trace logs with some additional logs that I added for debugging: