|
|
DescriptionDrop buffers in idle SSLClientSockets (and SSLServerSockets).
As part of this, significantly refactor how both classes handle the
transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs
follow the UNIX-style non-blocking I/O. Our net stack, however, is based
on asynchronous callbacks. Both socket had some complex code to bridge
the two I/O models.
Factor all this code into a SocketBIOAdapter. This takes a StreamSocket
and returns a BIO which acts on the socket. The UNIX model assumes
external knowledge of when to retry operations (usually a select loop),
so the SocketBIOAdapter has a delegate interface which signals
OnReadReady and OnWriteReady. By being factored out, it can also be
independently unit-tested, which is handy.
It also implements the weird hack we have where write errors route into
read errors. In doing so, it fixes a case where whether that error was
routed correctly depended on whether transport Writes failed
synchronously (if BufferSend synchronously succeeded in DoWriteLoop,
DoPayloadRead wasn't run, but it was run if asynchronous). This requires
tweaking a test expectation.
This removes uses of the bizarre "zero-copy" BIO pair stuff which can
now be removed from BoringSSL. It also unifies client and server I/O
handling which fixes transport error mapping on the
server. (Accordingly, some server test expectations also needed fixes.)
Oh, and on top of all this, actually drop the buffers when not needed as this
was sort of the point of this exercise. Having the code factored out makes this
a lot simpler to reason about and avoids adding even more complexity to BIO
pairs.
BUG=652456, 399455
Committed: https://crrev.com/3418e81ff9636db1d9e0de7c60e002788b51f5ea
Cr-Commit-Position: refs/heads/master@{#426097}
Patch Set 1 #Patch Set 2 : comments #Patch Set 3 : fix net_nacl #Patch Set 4 : rebase #Patch Set 5 : Self-review #Patch Set 6 : typo #
Total comments: 31
Patch Set 7 : rsleevi comments #
Total comments: 5
Patch Set 8 : mmenke comment #
Total comments: 4
Patch Set 9 : rsleevi comments #
Messages
Total messages: 52 (37 generated)
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by [email protected]
Dry run: Try jobs failed on following builders: ios-device on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/ios-device/builds...)
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by [email protected]
Dry run: Try jobs failed on following builders: ios-device on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/ios-device/builds...) ios-simulator on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/ios-simulator/bui...) mac_chromium_compile_dbg_ng on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_comp...) mac_chromium_rel_ng on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_rel_...)
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Description was changed from ========== Drop buffers in idle SSLClientSockets (and SSLServerSockets). As part of this, significantly refactor how both classes handle the transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs follow the UNIX-style non-blocking I/O. Our net stack, however, is based on asynchronous callbacks. Both socket had some complex code to bridge the two I/O models. Factor all this code into a SocketBIOAdapter. This takes a StreamSocket and returns a BIO which acts on the socket. The UNIX model assumes external knowledge of when to retry operations (usually a select loop), so the SocketBIOAdapter has a delegate interface which signals OnReadReady and OnWriteReady. It also implements the weird hack we have where write errors route into read errors. In doing so, it fixes a case where whether that error was routed correctly depended on whether transport Writes failed synchronously (if BufferSend synchronously succeeded in DoWriteLoop, DoPayloadRead wasn't run, but it was run if asynchronous). This requires tweaking a test expectation. By factoring this code out, it can be independently unit-tested and, notably for the bug at hand. This removes uses of the bizarre "zero-copy" BIO pair stuff which can now be removed from BoringSSL. It also unifies client and server I/O handling which fixes transport error mapping on the server. (Accordingly, some server test expectations also needed fixes.) Oh, and on top of all this, actually drop the buffers when not needed as this was sort of the point of this exercise. Having the code factored out makes this a lot simpler to reason about and avoids adding even more complexity to BIO pairs. BUG=652456,399455 ========== to ========== Drop buffers in idle SSLClientSockets (and SSLServerSockets). As part of this, significantly refactor how both classes handle the transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs follow the UNIX-style non-blocking I/O. Our net stack, however, is based on asynchronous callbacks. Both socket had some complex code to bridge the two I/O models. Factor all this code into a SocketBIOAdapter. This takes a StreamSocket and returns a BIO which acts on the socket. The UNIX model assumes external knowledge of when to retry operations (usually a select loop), so the SocketBIOAdapter has a delegate interface which signals OnReadReady and OnWriteReady. By being factored out, it can also be independently unit-tested, which is handy. It also implements the weird hack we have where write errors route into read errors. In doing so, it fixes a case where whether that error was routed correctly depended on whether transport Writes failed synchronously (if BufferSend synchronously succeeded in DoWriteLoop, DoPayloadRead wasn't run, but it was run if asynchronous). This requires tweaking a test expectation. This removes uses of the bizarre "zero-copy" BIO pair stuff which can now be removed from BoringSSL. It also unifies client and server I/O handling which fixes transport error mapping on the server. (Accordingly, some server test expectations also needed fixes.) Oh, and on top of all this, actually drop the buffers when not needed as this was sort of the point of this exercise. Having the code factored out makes this a lot simpler to reason about and avoids adding even more complexity to BIO pairs. BUG=652456,399455 ==========
The CQ bit was unchecked by [email protected]
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by [email protected] to run a CQ dry run
[email protected] changed reviewers: + [email protected], [email protected]
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
svaldez + eroman: We probably want to have multiple sets of eyes on this one. It's a non-trivial change. :-) Although hopefully decently tested and commented? rsleevi: CC'd you since you may have opinions here, but I'm guessing you're hosed. If you'd like for this change to wait on your review, give a holler.
[email protected] changed reviewers: + [email protected]
Ryan tells me he exists again, so moving up to the reviewers list. Probably still good to have Steven and Eric look at this too. If nothing else, so that more people know how this class works.
The CQ bit was unchecked by [email protected]
Dry run: Try jobs failed on following builders: android_arm64_dbg_recipe on master.tryserver.chromium.android (JOB_FAILED, https://build.chromium.org/p/tryserver.chromium.android/builders/android_arm6...)
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by [email protected]
Dry run: This issue passed the CQ dry run.
Thanks for working on this David! I probably won't get to this until Friday, but luckily you have better reviewers on the list already :)
Mostly LG, but some comments (mostly on comments) https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.cc (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:73: // bytes were received, intentionally read to the full buffer size. The SSL s/received/requested/ ? https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:102: DCHECK_LT(read_offset_, read_result_); CHECK_LT ? https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:108: if (read_offset_ >= read_result_) { Should read_offset_ ever be >? Seems like that would be a similar CHECKable sort of thing. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:120: // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so higher levels s/here so/here, so that/ https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:169: if (write_buffer_data_size_ < write_buffer_->RemainingCapacity()) { Naming wise, it was hard to tell the distinction between write_buffer_data_size and write_buffer_size - that is, I was trying to compare against line 157. is write_buffer_size_ really write_buffer_max_size_ ? and is write_buffer_data_size_ something like write_buffer_used_ ? https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:170: int todo = std::min( tocopy? https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:179: // If there is space and more data, fill the space before the starting offset. What's the difference between "front of the starting offset" and "space before the starting offset" ? https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:179: // If there is space and more data, fill the space before the starting offset. What variable represents "starting offset" ? https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.h (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:21: // An adapter to convert between StreamSocket and OpenSSL BIO I/O models. Could you expand a little more in this class description (which I think you did fine in the CL description) https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:24: class Delegate { Similarly, a little expansion on the Delegate (and perhaps suggested user pattern) https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:41: int write_buffer_size, style: Why int, instead of size_t? - https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md... https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:47: // Returns true if any data has been read from the underlying StreamSocket but nit: StreamSocket, but https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:67: static const BIO_METHOD kBIOMethod; This can be moved fully in the .cc, can it not? https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_client_... File net/socket/ssl_client_socket_impl.cc (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_client_... net/socket/ssl_client_socket_impl.cc:881: BIO_up_ref(transport_bio); // SSL_set_bio retains one reference. I'm not sure that the comment sufficiently explains why it's necessary to up_ref again. https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_server_... File net/socket/ssl_server_socket_impl.cc (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_server_... net/socket/ssl_server_socket_impl.cc:423: DCHECK(next_handshake_state_ == STATE_NONE); DCHECK_EQ? https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_server_... net/socket/ssl_server_socket_impl.cc:445: DCHECK(next_handshake_state_ == STATE_NONE); DCHECK_EQ?
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
[email protected] changed reviewers: + [email protected]
In fixing up an issue here, I noticed socket_test_util.cc didn't work. +mmenke to review those changes. (The set of reviewers on this CL is... entertaining...) https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.cc (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:73: // bytes were received, intentionally read to the full buffer size. The SSL On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > s/received/requested/ ? Done. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:102: DCHECK_LT(read_offset_, read_result_); On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > CHECK_LT ? Done. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:108: if (read_offset_ >= read_result_) { On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > Should read_offset_ ever be >? Seems like that would be a similar CHECKable sort > of thing. The (D)CHECK_LT above would impy it can't be. Switched it to == now that it's a CHECK. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:120: // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so higher levels On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > s/here so/here, so that/ Done. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:169: if (write_buffer_data_size_ < write_buffer_->RemainingCapacity()) { On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > Naming wise, it was hard to tell the distinction between write_buffer_data_size > and write_buffer_size - that is, I was trying to compare against line 157. is > write_buffer_size_ really write_buffer_max_size_ ? and is > write_buffer_data_size_ something like write_buffer_used_ ? Yeah. I switched it to size => capacity and data_size => used throughout. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:181: DCHECK_GE(write_buffer_data_size_, write_buffer_->RemainingCapacity()); So it turns out all this code was totally wrong anyway, so I reimplemented it and improved the test. And then I noticed that socket_test_utils.h has a bug which prevented the test from working, so that's now been fixed too. :-) https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.h (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:21: // An adapter to convert between StreamSocket and OpenSSL BIO I/O models. On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > Could you expand a little more in this class description (which I think you did > fine in the CL description) Done. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:24: class Delegate { On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > Similarly, a little expansion on the Delegate (and perhaps suggested user > pattern) Done. I kept the pattern a bit vague because it really depends on what you're doing with the SSL*. SSL{Client,Server}Socket's pattern is more a consequence of it mapping StreamSocket model -> OpenSSL model -> StreamSocket model, and this class is more concerned with the first arrow. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:41: int write_buffer_size, On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > style: Why int, instead of size_t? - > https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md... The entire net stack (and BIO for that matter...) uses int everywhere. I tried to have it use size_t but it ended up casting everywhere and not actually being safer. I think size_t-ing this ought to wait until we have a size_t story for Read and Write. Those two basically block everything else. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:47: // Returns true if any data has been read from the underlying StreamSocket but On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > nit: StreamSocket, but Done. https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:67: static const BIO_METHOD kBIOMethod; On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > This can be moved fully in the .cc, can it not? It needs to have access to the statics which, in turn, needs to have access to BIORead and BIOWrite which, in turn, ought to be private to the SocketBIOAdapter. We'd need the dummy friend class trick to avoid putting them in the header, and that seemed pointless. This header: a) Already must include BoringSSL's forward decl header for the public SocketBIOAdapter::bio. These bits don't force any additional headers be included. b) Is only used in three compilation units. c) Even if it did force an include of bio.h, each compilation unit which includes this header would include bio.h anyway. https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_client_... File net/socket/ssl_client_socket_impl.cc (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_client_... net/socket/ssl_client_socket_impl.cc:881: BIO_up_ref(transport_bio); // SSL_set_bio retains one reference. On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > I'm not sure that the comment sufficiently explains why it's necessary to up_ref > again. SSL_set_bio and friends take ownership. I've switched them to SSL_set0_[wr]bio which are less absurd[0] and tweaked the comment a little. [0] https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#S... https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_server_... File net/socket/ssl_server_socket_impl.cc (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_server_... net/socket/ssl_server_socket_impl.cc:423: DCHECK(next_handshake_state_ == STATE_NONE); On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > DCHECK_EQ? Done. https://codereview.chromium.org/2411033003/diff/100001/net/socket/ssl_server_... net/socket/ssl_server_socket_impl.cc:445: DCHECK(next_handshake_state_ == STATE_NONE); On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > DCHECK_EQ? Done.
https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.h (right): https://codereview.chromium.org/2411033003/diff/100001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:67: static const BIO_METHOD kBIOMethod; On 2016/10/13 23:40:13, davidben wrote: > On 2016/10/12 23:30:27, Ryan Sleevi (slow) wrote: > > This can be moved fully in the .cc, can it not? > > It needs to have access to the statics which, in turn, needs to have access to > BIORead and BIOWrite which, in turn, ought to be private to the > SocketBIOAdapter. We'd need the dummy friend class trick to avoid putting them > in the header, and that seemed pointless. This header: > > a) Already must include BoringSSL's forward decl header for the public > SocketBIOAdapter::bio. These bits don't force any additional headers be > included. > b) Is only used in three compilation units. > c) Even if it did force an include of bio.h, each compilation unit which > includes this header would include bio.h anyway. Oh, I guess (b) and (c) aren't true. It's in two additional compilation units (until the SSLClientContext refactor). But regardless it doesn't induce other headers. I don't think it makes sense to add a: friend class SocketBIOAdapterPrivateMethodHolder; and to move all the private methods (but not the fields) over here.
The CQ bit was unchecked by [email protected]
Dry run: This issue passed the CQ dry run.
socket_test_util LGTM https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... File net/socket/socket_test_util.cc (right): https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... net/socket/socket_test_util.cc:207: } If this isn't being used, should be just remove it instead? https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... net/socket/socket_test_util.cc:236: CHECK(0) << "No write data available."; nit: CHECK(false) is more common.
https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... File net/socket/socket_test_util.cc (right): https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... net/socket/socket_test_util.cc:207: } On 2016/10/14 14:57:39, mmenke wrote: > If this isn't being used, should be just remove it instead? Seems to be called in initialization. I was just reordering to match the header. https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... net/socket/socket_test_util.cc:236: CHECK(0) << "No write data available."; On 2016/10/14 14:57:39, mmenke wrote: > nit: CHECK(false) is more common. Done. C habits. :-)
https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... File net/socket/socket_test_util.cc (right): https://codereview.chromium.org/2411033003/diff/120001/net/socket/socket_test... net/socket/socket_test_util.cc:207: } On 2016/10/14 16:32:37, davidben wrote: > On 2016/10/14 14:57:39, mmenke wrote: > > If this isn't being used, should be just remove it instead? > > Seems to be called in initialization. I was just reordering to match the header. Oops, didn't notice that you moved it, as opposed to adding it.
So, overall, this LGTM, but I have one concern with the approach, highlighted below, because I think it assumes too much, even if it's safe as written. I gave one suggestion on how to rewrite, but I think there's probably more ways, and I trust your judgement. I did find the documentation in the unittests much more helpful when reading the code to compare the ring buffer. I know ring buffers are dead simple/stupid, but like quicksort, they can have subtle issues that aren't easily detected. https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.cc (right): https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:173: write_offset -= write_buffer_->capacity(); This approach makes me *super* nervous from a security perspective, because you're assuming no overflows here, and that's a subtle sort of assumption (ok, yes, 17K means in practice no overflows, but you get what I mean - it's a pattern match to a dangerous pattern) It's also subtle to parse out and understand what's going on here - that offset() represents the 'start' of the ring buffer, but that write_buffer_used_ may have wrapped around. One way would be to write it as an expression without the risk of overflow (that is, detect wrap-around by determining if write_buffer_->offset() >= write_buffer_->capacity() - write_buffer_used_ ; which indicates that start is after end), another would be to use the safe_numerics just to make the invariant clearly explicit. I know this is safe in practice, but it's just the trigger that it's dangerous code w/o any safety net. https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.h (right): https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:54: class Delegate { nit: Add protected virtual dtor, since you don't require explicit memory management as part of your API contract (that is, Delegate* outlives the BIOAdapter)
The CQ bit was checked by [email protected] to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.cc (right): https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... net/socket/socket_bio_adapter.cc:173: write_offset -= write_buffer_->capacity(); On 2016/10/18 01:30:17, Ryan Sleevi (at conf til 10-21 wrote: > This approach makes me *super* nervous from a security perspective, because > you're assuming no overflows here, and that's a subtle sort of assumption (ok, > yes, 17K means in practice no overflows, but you get what I mean - it's a > pattern match to a dangerous pattern) > > It's also subtle to parse out and understand what's going on here - that > offset() represents the 'start' of the ring buffer, but that write_buffer_used_ > may have wrapped around. > > One way would be to write it as an expression without the risk of overflow (that > is, detect wrap-around by determining if write_buffer_->offset() >= > write_buffer_->capacity() - write_buffer_used_ ; which indicates that start is > after end), another would be to use the safe_numerics just to make the invariant > clearly explicit. > > I know this is safe in practice, but it's just the trigger that it's dangerous > code w/o any safety net. Every way to write this involves different subtle invariants. :-) I rewrote it as a fixed version of the first iteration. How's this verison? https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... File net/socket/socket_bio_adapter.h (right): https://codereview.chromium.org/2411033003/diff/140001/net/socket/socket_bio_... net/socket/socket_bio_adapter.h:54: class Delegate { On 2016/10/18 01:30:17, Ryan Sleevi (at conf til 10-21 wrote: > nit: Add protected virtual dtor, since you don't require explicit memory > management as part of your API contract (that is, Delegate* outlives the > BIOAdapter) Done.
Thanks! LGTM
The CQ bit was unchecked by [email protected]
The CQ bit was checked by [email protected]
The patchset sent to the CQ was uploaded after l-g-t-m from [email protected] Link to the patchset: https://codereview.chromium.org/2411033003/#ps160001 (title: "rsleevi comments")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
Message was sent while issue was closed.
Description was changed from ========== Drop buffers in idle SSLClientSockets (and SSLServerSockets). As part of this, significantly refactor how both classes handle the transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs follow the UNIX-style non-blocking I/O. Our net stack, however, is based on asynchronous callbacks. Both socket had some complex code to bridge the two I/O models. Factor all this code into a SocketBIOAdapter. This takes a StreamSocket and returns a BIO which acts on the socket. The UNIX model assumes external knowledge of when to retry operations (usually a select loop), so the SocketBIOAdapter has a delegate interface which signals OnReadReady and OnWriteReady. By being factored out, it can also be independently unit-tested, which is handy. It also implements the weird hack we have where write errors route into read errors. In doing so, it fixes a case where whether that error was routed correctly depended on whether transport Writes failed synchronously (if BufferSend synchronously succeeded in DoWriteLoop, DoPayloadRead wasn't run, but it was run if asynchronous). This requires tweaking a test expectation. This removes uses of the bizarre "zero-copy" BIO pair stuff which can now be removed from BoringSSL. It also unifies client and server I/O handling which fixes transport error mapping on the server. (Accordingly, some server test expectations also needed fixes.) Oh, and on top of all this, actually drop the buffers when not needed as this was sort of the point of this exercise. Having the code factored out makes this a lot simpler to reason about and avoids adding even more complexity to BIO pairs. BUG=652456,399455 ========== to ========== Drop buffers in idle SSLClientSockets (and SSLServerSockets). As part of this, significantly refactor how both classes handle the transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs follow the UNIX-style non-blocking I/O. Our net stack, however, is based on asynchronous callbacks. Both socket had some complex code to bridge the two I/O models. Factor all this code into a SocketBIOAdapter. This takes a StreamSocket and returns a BIO which acts on the socket. The UNIX model assumes external knowledge of when to retry operations (usually a select loop), so the SocketBIOAdapter has a delegate interface which signals OnReadReady and OnWriteReady. By being factored out, it can also be independently unit-tested, which is handy. It also implements the weird hack we have where write errors route into read errors. In doing so, it fixes a case where whether that error was routed correctly depended on whether transport Writes failed synchronously (if BufferSend synchronously succeeded in DoWriteLoop, DoPayloadRead wasn't run, but it was run if asynchronous). This requires tweaking a test expectation. This removes uses of the bizarre "zero-copy" BIO pair stuff which can now be removed from BoringSSL. It also unifies client and server I/O handling which fixes transport error mapping on the server. (Accordingly, some server test expectations also needed fixes.) Oh, and on top of all this, actually drop the buffers when not needed as this was sort of the point of this exercise. Having the code factored out makes this a lot simpler to reason about and avoids adding even more complexity to BIO pairs. BUG=652456,399455 ==========
Message was sent while issue was closed.
Committed patchset #9 (id:160001)
Message was sent while issue was closed.
Description was changed from ========== Drop buffers in idle SSLClientSockets (and SSLServerSockets). As part of this, significantly refactor how both classes handle the transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs follow the UNIX-style non-blocking I/O. Our net stack, however, is based on asynchronous callbacks. Both socket had some complex code to bridge the two I/O models. Factor all this code into a SocketBIOAdapter. This takes a StreamSocket and returns a BIO which acts on the socket. The UNIX model assumes external knowledge of when to retry operations (usually a select loop), so the SocketBIOAdapter has a delegate interface which signals OnReadReady and OnWriteReady. By being factored out, it can also be independently unit-tested, which is handy. It also implements the weird hack we have where write errors route into read errors. In doing so, it fixes a case where whether that error was routed correctly depended on whether transport Writes failed synchronously (if BufferSend synchronously succeeded in DoWriteLoop, DoPayloadRead wasn't run, but it was run if asynchronous). This requires tweaking a test expectation. This removes uses of the bizarre "zero-copy" BIO pair stuff which can now be removed from BoringSSL. It also unifies client and server I/O handling which fixes transport error mapping on the server. (Accordingly, some server test expectations also needed fixes.) Oh, and on top of all this, actually drop the buffers when not needed as this was sort of the point of this exercise. Having the code factored out makes this a lot simpler to reason about and avoids adding even more complexity to BIO pairs. BUG=652456,399455 ========== to ========== Drop buffers in idle SSLClientSockets (and SSLServerSockets). As part of this, significantly refactor how both classes handle the transport. BoringSSL's SSL stack expects the transport as a BIO. BIOs follow the UNIX-style non-blocking I/O. Our net stack, however, is based on asynchronous callbacks. Both socket had some complex code to bridge the two I/O models. Factor all this code into a SocketBIOAdapter. This takes a StreamSocket and returns a BIO which acts on the socket. The UNIX model assumes external knowledge of when to retry operations (usually a select loop), so the SocketBIOAdapter has a delegate interface which signals OnReadReady and OnWriteReady. By being factored out, it can also be independently unit-tested, which is handy. It also implements the weird hack we have where write errors route into read errors. In doing so, it fixes a case where whether that error was routed correctly depended on whether transport Writes failed synchronously (if BufferSend synchronously succeeded in DoWriteLoop, DoPayloadRead wasn't run, but it was run if asynchronous). This requires tweaking a test expectation. This removes uses of the bizarre "zero-copy" BIO pair stuff which can now be removed from BoringSSL. It also unifies client and server I/O handling which fixes transport error mapping on the server. (Accordingly, some server test expectations also needed fixes.) Oh, and on top of all this, actually drop the buffers when not needed as this was sort of the point of this exercise. Having the code factored out makes this a lot simpler to reason about and avoids adding even more complexity to BIO pairs. BUG=652456,399455 Committed: https://crrev.com/3418e81ff9636db1d9e0de7c60e002788b51f5ea Cr-Commit-Position: refs/heads/master@{#426097} ==========
Message was sent while issue was closed.
Patchset 9 (id:??) landed as https://crrev.com/3418e81ff9636db1d9e0de7c60e002788b51f5ea Cr-Commit-Position: refs/heads/master@{#426097} |