-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Rent correct buffer size for SslStream.Encrypt #51060
Rent correct buffer size for SslStream.Encrypt #51060
Conversation
Tagging subscribers to this area: @dotnet/ncl, @vcsjones Issue DetailsSeen in #50921 (comment)
runtime/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs Lines 253 to 257 in 125253b
Change to rent Before After
|
src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs
Outdated
Show resolved
Hide resolved
We really shouldn't ever allocate in SslStreamPal.EncryptMessage; this is a legacy of previous times where we weren't very smart about buffer management. Now it's just hiding issues like this. Could we change that check to an assert? Is there any code depending on the current behavior? Could it be fixed? |
src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs
Outdated
Show resolved
Hide resolved
Out of curiosity, what values for header size and trailer size were you seeing? Presumably FrameOverhead was intended to be large enough to handle any cipher mode; but apparently it's not... |
Outputting when
I see the reallocation about 4% of the calls; but I assume a lot get hidden from |
Looks like the
|
Not sure; it can wait for renegotiation to finish and then call it with the original rented buffer; so the sizes could have changed at that point. However it should only be that rare corner case now? runtime/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs Lines 690 to 693 in 3cbbade
|
Is it possible to either (a) not rent the buffer until we know that we are not renegotiating; or (b) release the old rented buffer and rent a new one when renegotiation happens?
Yeah, renegotiation is not common and I don't really worry about the perf cost in that case. I'm more worried that if we continue to have the automatic fallback in the low-level Encrypt code, then it will hide perf problems in cases we care about, like the original one here. |
We should audit if there are other places we use FrameOverhead. |
Already does (b); however there is a race condition with renegotiation which happens in
Separate issue to resolve across SChannel, OpenSsl and AppleCrypto as they all use different apis to determine size? i.e. its currently always requesting a buffer that's too small; which is hidden 96% of the time due to ArrayPool's power of 2 round up, this resolves that and increases I agree it would be better not to have the fallback; but changing it to throw an exception instead is a bit more responsibility that I want to take in this PR 😉 |
I understand :) That said, if we are not going to do a comprehensive fix right now, then we should probably do something with minimal risk and file a separate issue to address this in a comprehensive way. To that end, maybe we should just bump Also adding @wfurt for his opinion. |
Something more like? #51320 |
Opened PR for the casting #51324 |
Will close this in favour of the other two |
Seen in #50921 (comment)
WriteSingleChunk
rents a buffer the size ofbuffer.Length + FrameOverhead
; however after the handshake the overhead is_headerSize + _trailerSize
which can be different and causes Encrypt to ignore the buffer and allocate its own of the correct size.runtime/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs
Lines 253 to 257 in 125253b
Change to rent
buffer.Length + _headerSize + _trailerSize
when these values are available.Also drop some unnecessary casting in the Pal layers by receiving the correct type rather than a less derived one.
Before
After
/cc @karelz @dotnet/ncl
Resolves #51076