• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/socket/socket_bio_adapter.h"
6 
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include <algorithm>
11 
12 #include "base/check_op.h"
13 #include "base/containers/span.h"
14 #include "base/debug/alias.h"
15 #include "base/functional/bind.h"
16 #include "base/location.h"
17 #include "base/notreached.h"
18 #include "base/numerics/safe_conversions.h"
19 #include "base/task/single_thread_task_runner.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/socket/socket.h"
23 #include "net/socket/stream_socket.h"
24 #include "net/ssl/openssl_ssl_util.h"
25 #include "net/traffic_annotation/network_traffic_annotation.h"
26 #include "third_party/boringssl/src/include/openssl/bio.h"
27 
28 namespace {
29 
30 const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
31     net::DefineNetworkTrafficAnnotation("socket_bio_adapter", R"(
32       semantics {
33         sender: "Socket BIO Adapter"
34         description:
35           "SocketBIOAdapter is used only internal to //net code as an internal "
36           "detail to implement a TLS connection for a Socket class, and is not "
37           "being called directly outside of this abstraction."
38         trigger:
39           "Establishing a TLS connection to a remote endpoint. There are many "
40           "different ways in which a TLS connection may be triggered, such as "
41           "loading an HTTPS URL."
42         data:
43           "All data sent or received over a TLS connection. This traffic may "
44           "either be the handshake or application data. During the handshake, "
45           "the target host name, user's IP, data related to previous "
46           "handshake, client certificates, and channel ID, may be sent. When "
47           "the connection is used to load an HTTPS URL, the application data "
48           "includes cookies, request headers, and the response body."
49         destination: OTHER
50         destination_other:
51           "Any destination the implementing socket is connected to."
52       }
53       policy {
54         cookies_allowed: NO
55         setting: "This feature cannot be disabled."
56         policy_exception_justification: "Essential for navigation."
57       })");
58 
59 }  // namespace
60 
61 namespace net {
62 
SocketBIOAdapter(StreamSocket * socket,int read_buffer_capacity,int write_buffer_capacity,Delegate * delegate)63 SocketBIOAdapter::SocketBIOAdapter(StreamSocket* socket,
64                                    int read_buffer_capacity,
65                                    int write_buffer_capacity,
66                                    Delegate* delegate)
67     : socket_(socket),
68       read_buffer_capacity_(read_buffer_capacity),
69       write_buffer_capacity_(write_buffer_capacity),
70       delegate_(delegate) {
71   bio_.reset(BIO_new(BIOMethod()));
72   BIO_set_data(bio_.get(), this);
73   BIO_set_init(bio_.get(), 1);
74 
75   read_callback_ = base::BindRepeating(&SocketBIOAdapter::OnSocketReadComplete,
76                                        weak_factory_.GetWeakPtr());
77   write_callback_ = base::BindRepeating(
78       &SocketBIOAdapter::OnSocketWriteComplete, weak_factory_.GetWeakPtr());
79 }
80 
81 SocketBIOAdapter::~SocketBIOAdapter() {
82   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
83   // BIOs are reference-counted and may outlive the adapter. Clear the pointer
84   // so future operations fail.
85   BIO_set_data(bio_.get(), nullptr);
86 }
87 
88 bool SocketBIOAdapter::HasPendingReadData() {
89   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
90   return read_result_ > 0;
91 }
92 
93 size_t SocketBIOAdapter::GetAllocationSize() const {
94   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
95   size_t buffer_size = 0;
96   if (read_buffer_)
97     buffer_size += read_buffer_capacity_;
98 
99   if (write_buffer_)
100     buffer_size += write_buffer_capacity_;
101   return buffer_size;
102 }
103 
104 int SocketBIOAdapter::BIORead(base::span<uint8_t> out) {
105   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
106   if (out.empty()) {
107     return 0;
108   }
109 
110   // If there is no result available synchronously, report any Write() errors
111   // that were observed. Otherwise the application may have encountered a socket
112   // error while writing that would otherwise not be reported until the
113   // application attempted to write again - which it may never do. See
114   // https://crbug.com/249848.
115   if (write_error_ != OK && write_error_ != ERR_IO_PENDING &&
116       (read_result_ == 0 || read_result_ == ERR_IO_PENDING)) {
117     OpenSSLPutNetError(FROM_HERE, write_error_);
118     return -1;
119   }
120 
121   if (read_result_ == 0) {
122     // Instantiate the read buffer and read from the socket. Although only |len|
123     // bytes were requested, intentionally read to the full buffer size. The SSL
124     // layer reads the record header and body in separate reads to avoid
125     // overreading, but issuing one is more efficient. SSL sockets are not
126     // reused after shutdown for non-SSL traffic, so overreading is fine.
127     CHECK(!read_buffer_);
128     CHECK_EQ(0u, read_offset_);
129     read_buffer_ =
130         base::MakeRefCounted<IOBufferWithSize>(read_buffer_capacity_);
131     read_result_ = ERR_IO_PENDING;
132     int result = socket_->ReadIfReady(
133         read_buffer_.get(), read_buffer_capacity_,
134         base::BindOnce(&SocketBIOAdapter::OnSocketReadIfReadyComplete,
135                        weak_factory_.GetWeakPtr()));
136     if (result == ERR_IO_PENDING)
137       read_buffer_ = nullptr;
138     if (result == ERR_READ_IF_READY_NOT_IMPLEMENTED) {
139       result = socket_->Read(read_buffer_.get(), read_buffer_capacity_,
140                              read_callback_);
141     }
142     if (result != ERR_IO_PENDING) {
143       // `HandleSocketReadResult` will update `read_result_` based on `result`.
144       HandleSocketReadResult(result);
145     }
146   }
147 
148   // There is a pending Read(). Inform the caller to retry when it completes.
149   if (read_result_ == ERR_IO_PENDING) {
150     BIO_set_retry_read(bio());
151     return -1;
152   }
153 
154   // If the last Read() failed, report the error.
155   if (read_result_ < 0) {
156     OpenSSLPutNetError(FROM_HERE, read_result_);
157     return -1;
158   }
159 
160   // Report the result of the last Read() if non-empty.
161   const auto read_result_s = static_cast<size_t>(read_result_);
162   CHECK_LT(read_offset_, read_result_s);
163   base::span<const uint8_t> read_data = read_buffer_->span().subspan(
164       read_offset_, std::min(out.size(), read_result_s - read_offset_));
165   out.copy_prefix_from(read_data);
166   read_offset_ += read_data.size();
167 
168   // Release the buffer when empty.
169   if (read_offset_ == read_result_s) {
170     read_buffer_ = nullptr;
171     read_offset_ = 0;
172     read_result_ = 0;
173   }
174 
175   return read_data.size();
176 }
177 
178 void SocketBIOAdapter::HandleSocketReadResult(int result) {
179   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
180   CHECK_NE(ERR_IO_PENDING, result);
181   CHECK_EQ(ERR_IO_PENDING, read_result_);
182 
183   // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here, so that higher
184   // levels don't report success.
185   if (result == 0)
186     result = ERR_CONNECTION_CLOSED;
187 
188   read_result_ = result;
189 
190   // The read buffer is no longer needed.
191   if (read_result_ <= 0)
192     read_buffer_ = nullptr;
193 }
194 
195 void SocketBIOAdapter::OnSocketReadComplete(int result) {
196   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
197   CHECK_EQ(ERR_IO_PENDING, read_result_);
198 
199   HandleSocketReadResult(result);
200   delegate_->OnReadReady();
201 }
202 
203 void SocketBIOAdapter::OnSocketReadIfReadyComplete(int result) {
204   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
205   CHECK_EQ(ERR_IO_PENDING, read_result_);
206   CHECK_GE(OK, result);
207 
208   // Do not use HandleSocketReadResult() because result == OK doesn't mean EOF.
209   read_result_ = result;
210 
211   delegate_->OnReadReady();
212 }
213 
214 int SocketBIOAdapter::BIOWrite(base::span<const uint8_t> in) {
215   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
216   if (in.empty()) {
217     return 0;
218   }
219 
220   // If the write buffer is not empty, there must be a pending Write() to flush
221   // it.
222   CHECK(write_buffer_used_ == 0 || write_error_ == ERR_IO_PENDING);
223 
224   // If a previous Write() failed, report the error.
225   if (write_error_ != OK && write_error_ != ERR_IO_PENDING) {
226     OpenSSLPutNetError(FROM_HERE, write_error_);
227     return -1;
228   }
229 
230   // Instantiate the write buffer if needed.
231   if (!write_buffer_) {
232     CHECK_EQ(0u, write_buffer_used_);
233     write_buffer_ = base::MakeRefCounted<GrowableIOBuffer>();
234     write_buffer_->SetCapacity(write_buffer_capacity_);
235   }
236 
237   // If the ring buffer is full, inform the caller to try again later.
238   if (write_buffer_used_ == static_cast<size_t>(write_buffer_->capacity())) {
239     BIO_set_retry_write(bio());
240     return -1;
241   }
242 
243   int bytes_copied = 0;
244 
245   // If there is space after the offset, fill it.
246   const auto remaining_capacity =
247       base::checked_cast<size_t>(write_buffer_->RemainingCapacity());
248   if (write_buffer_used_ < remaining_capacity) {
249     base::span<const uint8_t> chunk =
250         in.first(std::min(remaining_capacity - write_buffer_used_, in.size()));
251     write_buffer_->span().subspan(write_buffer_used_).copy_prefix_from(chunk);
252     in = in.subspan(chunk.size());
253     bytes_copied += chunk.size();
254     write_buffer_used_ += chunk.size();
255   }
256 
257   // If there is still space for remaining data, try to wrap around.
258   if (in.size() > 0 && write_buffer_used_ < base::checked_cast<size_t>(
259                                                 write_buffer_->capacity())) {
260     // If there were any room after the offset, the previous branch would have
261     // filled it.
262     CHECK_LE(remaining_capacity, write_buffer_used_);
263     const size_t write_offset = write_buffer_used_ - remaining_capacity;
264     base::span<const uint8_t> chunk = in.first(
265         std::min(in.size(), write_buffer_->capacity() - write_buffer_used_));
266     write_buffer_->everything().subspan(write_offset).copy_prefix_from(chunk);
267     in = in.subspan(chunk.size());
268     bytes_copied += chunk.size();
269     write_buffer_used_ += chunk.size();
270   }
271 
272   // Either the buffer is now full or there is no more input.
273   CHECK(in.empty() ||
274         write_buffer_used_ == static_cast<size_t>(write_buffer_->capacity()));
275 
276   // Schedule a socket Write() if necessary. (The ring buffer may previously
277   // have been empty.)
278   SocketWrite();
279 
280   // If a read-interrupting write error was synchronously discovered,
281   // asynchronously notify OnReadReady. See https://crbug.com/249848. Avoid
282   // reentrancy by deferring it to a later event loop iteration.
283   if (write_error_ != OK && write_error_ != ERR_IO_PENDING &&
284       read_result_ == ERR_IO_PENDING) {
285     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
286         FROM_HERE, base::BindOnce(&SocketBIOAdapter::CallOnReadReady,
287                                   weak_factory_.GetWeakPtr()));
288   }
289 
290   return bytes_copied;
291 }
292 
293 void SocketBIOAdapter::SocketWrite() {
294   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
295   while (write_error_ == OK && write_buffer_used_ > 0) {
296     const size_t write_buffer_used_old = write_buffer_used_;
297     const auto write_size = static_cast<int>(std::min(
298         write_buffer_used_,
299         base::checked_cast<size_t>(write_buffer_->RemainingCapacity())));
300 
301     // TODO(crbug.com/40064248): Remove this once the crash is resolved.
302     char debug[128];
303     snprintf(debug, sizeof(debug),
304              "offset=%d;remaining=%d;used=%zu;write_size=%d",
305              write_buffer_->offset(), write_buffer_->RemainingCapacity(),
306              write_buffer_used_, write_size);
307     base::debug::Alias(debug);
308 
309     write_error_ = ERR_IO_PENDING;
310     int result = socket_->Write(write_buffer_.get(), write_size,
311                                 write_callback_, kTrafficAnnotation);
312 
313     // TODO(crbug.com/40064248): Remove this once the crash is resolved.
314     char debug2[32];
315     snprintf(debug2, sizeof(debug2), "result=%d", result);
316     base::debug::Alias(debug2);
317 
318     // If `write_buffer_used_` changed across a call to the underlying socket,
319     // something went very wrong.
320     //
321     // TODO(crbug.com/40064248): Remove this once the crash is resolved.
322     CHECK_EQ(write_buffer_used_old, write_buffer_used_);
323     if (result != ERR_IO_PENDING) {
324       // `HandleSocketWriteResult` will update `write_error_` based on `result.
325       HandleSocketWriteResult(result);
326     }
327   }
328 }
329 
HandleSocketWriteResult(int result)330 void SocketBIOAdapter::HandleSocketWriteResult(int result) {
331   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
332   CHECK_NE(ERR_IO_PENDING, result);
333   CHECK_EQ(ERR_IO_PENDING, write_error_);
334 
335   if (result < 0) {
336     write_error_ = result;
337 
338     // The write buffer is no longer needed.
339     write_buffer_ = nullptr;
340     write_buffer_used_ = 0;
341     return;
342   }
343 
344   // Advance the ring buffer.
345   CHECK_LE(static_cast<size_t>(result), write_buffer_used_);
346   CHECK_LE(result, write_buffer_->RemainingCapacity());
347   write_buffer_->set_offset(write_buffer_->offset() + result);
348   write_buffer_used_ -= result;
349   if (write_buffer_->RemainingCapacity() == 0)
350     write_buffer_->set_offset(0);
351   write_error_ = OK;
352 
353   // Release the write buffer if empty.
354   if (write_buffer_used_ == 0)
355     write_buffer_ = nullptr;
356 }
357 
358 void SocketBIOAdapter::OnSocketWriteComplete(int result) {
359   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
360   CHECK_EQ(ERR_IO_PENDING, write_error_);
361 
362   bool was_full =
363       write_buffer_used_ == static_cast<size_t>(write_buffer_->capacity());
364 
365   HandleSocketWriteResult(result);
366   SocketWrite();
367 
368   // If transitioning from being unable to accept data to being able to, signal
369   // OnWriteReady.
370   if (was_full) {
371     base::WeakPtr<SocketBIOAdapter> guard(weak_factory_.GetWeakPtr());
372     delegate_->OnWriteReady();
373     // OnWriteReady may delete the adapter.
374     if (!guard)
375       return;
376   }
377 
378   // Write errors are fed back into BIO_read once the read buffer is empty. If
379   // BIO_read is currently blocked, signal early that a read result is ready.
380   if (result < 0 && read_result_ == ERR_IO_PENDING)
381     delegate_->OnReadReady();
382 }
383 
384 void SocketBIOAdapter::CallOnReadReady() {
385   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
386   if (read_result_ == ERR_IO_PENDING)
387     delegate_->OnReadReady();
388 }
389 
390 SocketBIOAdapter* SocketBIOAdapter::GetAdapter(BIO* bio) {
391   SocketBIOAdapter* adapter =
392       reinterpret_cast<SocketBIOAdapter*>(BIO_get_data(bio));
393   if (adapter) {
394     CHECK_EQ(bio, adapter->bio());
395   }
396   return adapter;
397 }
398 
399 // TODO(tsepez): should be declared UNSAFE_BUFFER_USAGE in header.
400 int SocketBIOAdapter::BIOWriteWrapper(BIO* bio, const char* in, int len) {
401   BIO_clear_retry_flags(bio);
402 
403   SocketBIOAdapter* adapter = GetAdapter(bio);
404   if (!adapter) {
405     OpenSSLPutNetError(FROM_HERE, ERR_UNEXPECTED);
406     return -1;
407   }
408 
409   return adapter->BIOWrite(base::as_bytes(
410       // SAFETY: The caller must ensure `in` points to `len` bytes.
411       // TODO(crbug.com/354307327): Spanify this method.
412       UNSAFE_TODO(base::span(in, base::checked_cast<size_t>(len)))));
413 }
414 
415 // TODO(tsepez): should be declared UNSAFE_BUFFER_USAGE in header.
416 int SocketBIOAdapter::BIOReadWrapper(BIO* bio, char* out, int len) {
417   BIO_clear_retry_flags(bio);
418 
419   SocketBIOAdapter* adapter = GetAdapter(bio);
420   if (!adapter) {
421     OpenSSLPutNetError(FROM_HERE, ERR_UNEXPECTED);
422     return -1;
423   }
424 
425   return adapter->BIORead(base::as_writable_bytes(
426       // SAFETY: The caller must ensure `out` points to `len` bytes.
427       // TODO(crbug.com/354307327): Spanify this method.
428       UNSAFE_TODO(base::span(out, base::checked_cast<size_t>(len)))));
429 }
430 
431 long SocketBIOAdapter::BIOCtrlWrapper(BIO* bio,
432                                       int cmd,
433                                       long larg,
434                                       void* parg) {
435   switch (cmd) {
436     case BIO_CTRL_FLUSH:
437       // The SSL stack requires BIOs handle BIO_flush.
438       return 1;
439   }
440 
441   NOTIMPLEMENTED();
442   return 0;
443 }
444 
445 const BIO_METHOD* SocketBIOAdapter::BIOMethod() {
446   static const BIO_METHOD* kMethod = []() {
447     BIO_METHOD* method = BIO_meth_new(0, nullptr);
448     CHECK(method);
449     CHECK(BIO_meth_set_write(method, SocketBIOAdapter::BIOWriteWrapper));
450     CHECK(BIO_meth_set_read(method, SocketBIOAdapter::BIOReadWrapper));
451     CHECK(BIO_meth_set_ctrl(method, SocketBIOAdapter::BIOCtrlWrapper));
452     return method;
453   }();
454   return kMethod;
455 }
456 
457 }  // namespace net
458