Skip to content

fix SSL write crash when write buffer has a very large chain#592

Merged
mattklein123 merged 2 commits intomasterfrom
fix_ssl_write_crash
Mar 20, 2017
Merged

fix SSL write crash when write buffer has a very large chain#592
mattklein123 merged 2 commits intomasterfrom
fix_ssl_write_crash

Conversation

@mattklein123
Copy link
Member

Previously, we would get all buffer slices on the stack and stack overflow
if the chain was very large. This change limits the number of slices that we
write during each iteration. There are a number of potential improvements
possible in terms of collapsing small moves, enforcing fairness in terms of
number of iterations, etc.

This commit also removes a bunch of RawSlice to evbuffer_iovec conversions
for performance reasons.

NOTE: The added test repros the crash before the fix.

fixes #585

Previously, we would get all buffer slices on the stack and stack overflow
if the chain was very large. This change limits the number of slices that we
write during each iteration. There are a number of potential improvements
possible in terms of collapsing small moves, enforcing fairness in terms of
number of iterations, etc.

This commit also removes a bunch of RawSlice to evbuffer_iovec conversions
for performance reasons.

NOTE: The added test repros the crash before the fix.

fixes #585
@mattklein123
Copy link
Member Author

@lyft/network-team @htuch

}
uint64_t total_bytes_written = 0;
bool keep_writing = true;
while (write_buffer_.length() && keep_writing) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Prefer explicit write_buffer_.length() > 0.

}

return {PostIoAction::KeepOpen, bytes_written};
return {PostIoAction::KeepOpen, total_bytes_written};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other locations where the Buffer::RawSlices slices[num_slices] pattern appears (from a grep), e.g. source/common/http/http1/codec_impl.cc. Naively it seems similar concerns would exist there. Is there an easy way to avoid this stack overflow danger globally?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately there is no global way to do this, since the code currently assumes that it returns all slices, or the size of the slices array required to hold them all. I will put in a TODO to figure this out and clean this up globally. I want to get a fix for this crash out since we saw this in production.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #593 instead of a TODO.

if (bytes_written > 0) {
write_buffer_.drain(bytes_written);
if (inner_bytes_written > 0) {
write_buffer_.drain(inner_bytes_written);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any advantage to draining outside the loop instead of on each iteration?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't drain during the loop, we keep getting the same slices at the beginning. I will put in a comment.

// RawSlice is the same structure as evbuffer_iovec. This was put into place to avoid leaking
// libevent into most code since we will likely replace evbuffer with our own implementation at
// some point. However, we can avoid a bunch of copies since the structure is the same.
static_assert(sizeof(RawSlice) == sizeof(evbuffer_iovec), "RawSlice != evbuffer_iovec");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup.

@mattklein123
Copy link
Member Author

@htuch updated

@htuch
Copy link
Member

htuch commented Mar 20, 2017

LGTM.

@mattklein123 mattklein123 merged commit 93bc377 into master Mar 20, 2017
@mattklein123 mattklein123 deleted the fix_ssl_write_crash branch March 20, 2017 18:26
mattklein123 added a commit that referenced this pull request Mar 21, 2017
This is a regression from #592 due to some truly awesome libevent
behavior. See commit comments for more info.
mattklein123 added a commit that referenced this pull request Mar 21, 2017
This is a regression from #592 due to some truly awesome libevent
behavior. See commit comments for more info.
rshriram pushed a commit to rshriram/envoy that referenced this pull request Oct 30, 2018
Automatic merge from submit-queue

[DO NOT MERGE] Auto PR to update dependencies of proxy

This PR will be merged automatically once checks are successful.
```release-note
none
```
PiotrSikora pushed a commit to PiotrSikora/envoy that referenced this pull request Aug 7, 2020
Signed-off-by: John Plevyak <jplevyak@gmail.com>
jplevyak added a commit to jplevyak/envoy that referenced this pull request Oct 2, 2020
GregHanson pushed a commit to istio/envoy that referenced this pull request Apr 4, 2023
…se-116

[release-1.16] 2023 04 04 release 116
mathetake added a commit that referenced this pull request Mar 3, 2026
**Commit Message**

This was too strict as a repo-wide rule, so this commit removes it.

Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSL connection write event crash

3 participants