Skip to content

Fix SSL_OP_IGNORE_UNEXPECTED_EOF being ignored over sockets#3341

Merged
prasden merged 2 commits into
aws:mainfrom
prasden:fix-bio-eof
Jul 14, 2026
Merged

Fix SSL_OP_IGNORE_UNEXPECTED_EOF being ignored over sockets#3341
prasden merged 2 commits into
aws:mainfrom
prasden:fix-bio-eof

Conversation

@prasden

@prasden prasden commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Issues:

Addresses V2066643219

Description of changes:

Follow-up to #3294, which gated SSL_OP_IGNORE_UNEXPECTED_EOF on BIO_eof(ssl->rbio.get()).

BIO_eof() calls BIO_ctrl(bio, BIO_CTRL_EOF, …), and socket BIOs (BIO_s_socket, used by SSL_set_fd in CPython) don't implement it, and sock_ctrl falls through to default: ret = 0, so the guard was always false and the condition was never met.

The testing didn't catch this because it used BIO_pair, which does implement BIO_CTRL_EOF and returns 1 at EOF so the guard passed in the test. Will need to be backported to the FIPS 3.0 and 4.0 branches.

Testing:

Added a test that reads through a dummy BIO that emulates a socket, as it returns 0 on read, and checks the client and server both get SSL_ERROR_ZERO_RETURN on an unexpected EOF. Confirmed the test fails with the old guard and passes with the fix.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

@prasden
prasden requested a review from a team as a code owner July 8, 2026 21:50
@prasden prasden changed the title Fix SSL_OP_IGNORE_UNEXPECTED_EOF for socket BIOs Fix SSL_OP_IGNORE_UNEXPECTED_EOF being ignored over sockets Jul 8, 2026
The guard added in aws#3294 gated the unexpected-EOF handling on
BIO_eof(rbio). Socket BIOs (BIO_s_socket, used by SSL_set_fd) do not
implement BIO_CTRL_EOF, so BIO_eof() returns 0 and the condition was
always false. As a result SSL_OP_IGNORE_UNEXPECTED_EOF had no effect on
real TCP connections and callers such as CPython still saw
SSL_ERROR_SYSCALL on an unexpected EOF.

Remove the BIO_eof() term so the option works for any transport that
returns 0 on a read with no close_notify.

Rework the test to use a socket-mimicking read BIO whose ctrl handler
returns 0 for all commands, so BIO_eof() reports 0 like a real socket.
The prior test used BIO_pair, which implements BIO_CTRL_EOF and therefore
passed even with the buggy guard; the new test fails with the guard
present and passes without it, covering both the client and server roles.
@codecov-commenter

codecov-commenter commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.18%. Comparing base (a8911af) to head (3e48d17).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3341      +/-   ##
==========================================
+ Coverage   78.17%   78.18%   +0.01%     
==========================================
  Files         693      693              
  Lines      123956   123959       +3     
  Branches    17213    17212       -1     
==========================================
+ Hits        96899    96915      +16     
+ Misses      26137    26125      -12     
+ Partials      920      919       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

Copy link
Copy Markdown
Contributor

🔒 Security ReviewView Report

Please review before merging.

@prasden
prasden enabled auto-merge (squash) July 14, 2026 18:40
@prasden
prasden merged commit 4cec1f7 into aws:main Jul 14, 2026
501 of 505 checks passed
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
Fix SSL_OP_IGNORE_UNEXPECTED_EOF for socket BIOs (aws#3341)
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
Fix SSL_OP_IGNORE_UNEXPECTED_EOF being ignored over sockets (aws#3341)
github-actions Bot pushed a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
### Issues:
Addresses `V2066643219`

### Description of changes:
Follow-up to aws#3294, which gated `SSL_OP_IGNORE_UNEXPECTED_EOF` on
[`BIO_eof(ssl->rbio.get())`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/ssl/ssl_buffer.cc#L585-L591).

[`BIO_eof()`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L443)
calls [`BIO_ctrl(bio, BIO_CTRL_EOF,
…)`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L390),
and socket BIOs (`BIO_s_socket`, used by
[`SSL_set_fd`](https://github.com/python/cpython/blob/main/Modules/_ssl.c#L985)
in CPython) don't implement it, and
[`sock_ctrl`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/socket.c#L106)
falls through to `default: ret = 0`, so the guard was always false and
the condition was never met.

The testing didn't catch this because it used
[`BIO_pair`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/pair.c#L381),
which does implement `BIO_CTRL_EOF` and returns 1 at EOF so the guard
passed in the test. Will need to be backported to the FIPS 3.0 and 4.0
branches.

### Testing:
Added a test that reads through a dummy BIO that emulates a socket, as
it returns 0 on read, and checks the client and server both get
`SSL_ERROR_ZERO_RETURN` on an unexpected EOF. Confirmed the test fails
with the old guard and passes with the fix.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 4cec1f7)
github-actions Bot pushed a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
### Issues:
Addresses `V2066643219`

### Description of changes:
Follow-up to aws#3294, which gated `SSL_OP_IGNORE_UNEXPECTED_EOF` on
[`BIO_eof(ssl->rbio.get())`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/ssl/ssl_buffer.cc#L585-L591).

[`BIO_eof()`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L443)
calls [`BIO_ctrl(bio, BIO_CTRL_EOF,
…)`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L390),
and socket BIOs (`BIO_s_socket`, used by
[`SSL_set_fd`](https://github.com/python/cpython/blob/main/Modules/_ssl.c#L985)
in CPython) don't implement it, and
[`sock_ctrl`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/socket.c#L106)
falls through to `default: ret = 0`, so the guard was always false and
the condition was never met.

The testing didn't catch this because it used
[`BIO_pair`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/pair.c#L381),
which does implement `BIO_CTRL_EOF` and returns 1 at EOF so the guard
passed in the test. Will need to be backported to the FIPS 3.0 and 4.0
branches.

### Testing:
Added a test that reads through a dummy BIO that emulates a socket, as
it returns 0 on read, and checks the client and server both get
`SSL_ERROR_ZERO_RETURN` on an unexpected EOF. Confirmed the test fails
with the old guard and passes with the fix.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.

(cherry picked from commit 4cec1f7)
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
Fix SSL_OP_IGNORE_UNEXPECTED_EOF being ignored over sockets (aws#3341)
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
tianyiy-tim added a commit to tianyiy-tim/aws-lc that referenced this pull request Jul 15, 2026
Fix SSL_OP_IGNORE_UNEXPECTED_EOF being ignored over sockets (aws#3341)
prasden added a commit that referenced this pull request Jul 20, 2026
…over sockets (#3359)

Backport #3341 

### Issues:
Addresses `V2066643219` 

### Description of changes: 
Follow-up to #3294, which gated `SSL_OP_IGNORE_UNEXPECTED_EOF` on
[`BIO_eof(ssl->rbio.get())`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/ssl/ssl_buffer.cc#L585-L591).


[`BIO_eof()`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L443)
calls [`BIO_ctrl(bio, BIO_CTRL_EOF,
…)`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L390),
and socket BIOs (`BIO_s_socket`, used by
[`SSL_set_fd`](https://github.com/python/cpython/blob/main/Modules/_ssl.c#L985)
in CPython) don't implement it, and
[`sock_ctrl`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/socket.c#L106)
falls through to `default: ret = 0`, so the guard was always false and
the condition was never met.

The testing didn't catch this because it used
[`BIO_pair`](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/pair.c#L381),
which does implement `BIO_CTRL_EOF` and returns 1 at EOF so the guard
passed in the test. Will need to be backported to the FIPS 3.0 and 4.0
branches.

### Testing:
Added a test that reads through a dummy BIO that emulates a socket, as
it returns 0 on read, and checks the client and server both get
`SSL_ERROR_ZERO_RETURN` on an unexpected EOF. Confirmed the test fails
with the old guard and passes with the fix.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
prasden added a commit that referenced this pull request Jul 20, 2026
…d over sockets (#3341) (#3360)

Backport #3341

### Issues:
Addresses `V2066643219`

### Description of changes:
Follow-up to #3294, which gated
SSL_OP_IGNORE_UNEXPECTED_EOF on
[BIO_eof(ssl->rbio.get())](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/ssl/ssl_buffer.cc#L585-L591).


[BIO_eof()](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L443)
calls [BIO_ctrl(bio, BIO_CTRL_EOF,
…)](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/bio.c#L390),
and socket BIOs (BIO_s_socket, used by
[SSL_set_fd](https://github.com/python/cpython/blob/main/Modules/_ssl.c#L985)
in CPython) don't implement it, and
[sock_ctrl](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/socket.c#L106)
falls through to default: ret = 0, so the guard was always false and the
condition was never met.

The testing didn't catch this because it used
[BIO_pair](https://github.com/aws/aws-lc/blob/23df900e6df447bcebfd3e41b4851aad1ab2cc19/crypto/bio/pair.c#L381),
which does implement BIO_CTRL_EOF and returns 1 at EOF so the guard
passed in the test. Will need to be backported to the FIPS 3.0 and 4.0
branches.

### Testing:
Added a test that reads through a dummy BIO that emulates a socket, as
it returns 0 on read, and checks the client and server both get
SSL_ERROR_ZERO_RETURN on an unexpected EOF. Confirmed the test fails
with the old guard and passes with the fix.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
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.

4 participants