Fix non-blocking connect completion check in BIO.

Previously, we polled getsockopt(SO_ERROR) to check if a non-blocking connect
had completed, but this isn't right. SO_ERROR is only set *after* the
connect succeeded or failed.

Until then, you have to wait until the socket is writable. Per
connect(2) on Linux:

> The socket is nonblocking and the connection cannot be completed
> immediately.  (UNIX domain sockets failed with EAGAIN instead.)  It
> is  possible to select(2) or poll(2) for completion by selecting the
> socket for writing.  After select(2) indicates writability, use
> getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to
> determine whether connect()  completed  successfully  (SO_ERROR  is
> zero) or unsuccessfully (SO_ERROR is one of the usual error codes
> listed here, explaining the reason for the failure).

Windows documentation says something similar:

> With a nonblocking socket, the connection attempt cannot be completed
> immediately. In this case, connect will return SOCKET_ERROR, and
> WSAGetLastError will return WSAEWOULDBLOCK. In this case, there are
> three possible scenarios:
>
> * Use the select function to determine the completion of the
>   connection request by checking to see if the socket is writable.

https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect

This means that, even though BIO is generally not responsible for
calling select/poll, we need to do it here. Use poll on POSIX because
select cannot monitor fds beyond FD_SETSIZE. (Winsock's select does not
have this limitation. nfds is ignored.)

As part of this, remove the weird zero return from conn_state when
connect fails the second time around. It would make more sense to behave
the same between the two, and this actually would have caused BIO_read
to mistakenly report EOF when implicitly driving the connect state. No
one could have been relying on this because this code didn't work
anyway. To that end, it seems unlikely anyone is using non-blocking
connect BIOs because they don't work at all.

Change-Id: Iaf4c58920e686eadcfbb215f43cf9d90fa35f56d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/96189
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
4 files changed
tree: c829a45982110c4f46004897c74e00f99fa769e0
  1. .bcr/
  2. .github/
  3. bench/
  4. cmake/
  5. crypto/
  6. decrepit/
  7. docs/
  8. fuzz/
  9. gen/
  10. include/
  11. infra/
  12. pki/
  13. rust/
  14. ssl/
  15. third_party/
  16. tool/
  17. util/
  18. .bazelignore
  19. .bazelrc
  20. .bazelversion
  21. .clang-format
  22. .clang-format-ignore
  23. .clangd
  24. .gitattributes
  25. .gitignore
  26. API-CONVENTIONS.md
  27. AUTHORS
  28. BREAKING-CHANGES.md
  29. BUILD.bazel
  30. build.json
  31. BUILDING.md
  32. CMakeLists.txt
  33. codereview.settings
  34. CONTRIBUTING.md
  35. FUZZING.md
  36. go.mod
  37. go.sum
  38. INCORPORATING.md
  39. LICENSE
  40. MODULE.bazel
  41. MODULE.bazel.lock
  42. PORTING.md
  43. PRESUBMIT.py
  44. PrivacyInfo.xcprivacy
  45. README.md
  46. SANDBOXING.md
  47. SECURITY.md
  48. STYLE.md
README.md

BoringSSL

BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.

Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.

Programs ship their own copies of BoringSSL when they use it and we update everything as needed when deciding to make API changes. This allows us to mostly avoid compromises in the name of compatibility. It works for us, but it may not work for you.

BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved in maintaining all these patches in multiple places was growing steadily.

Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the NDK) and a number of other apps/programs.

Project links:

To file a security issue, use the Chromium process and mention in the report this is for BoringSSL. You can ignore the parts of the process that are specific to Chromium/Chrome.

There are other files in this directory which might be helpful: