-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove race condition when creating new HTTPChannel #435
Conversation
No longer call getpeername() on the remote socket either, as it is not necessary for any of the places where waitress requires that self.addr in a subclass of the dispatcher needs it. This removes a race condition when setting up a HTTPChannel where we accepted the socket, and know the remote address, yet call getpeername() again which would have the unintended side effect of potentially setting self.connected to False because the remote has already shut down part of the socket. This issue was uncovered in #418, where the server would go into a hard loop because self.connected was used in various parts of the code base.
Calling handle_close() multiple times does not hurt anything, and is safe.
ef3833d
to
ff7e3c1
Compare
This avoids calling close() twice on the same socket if self.close() or self.handle_close() is called multiple times
ff7e3c1
to
9d99c89
Compare
@digitalresistor it's been running for a few weeks with no problem. the pentests still happen and we haven't see any problems. |
great, find and thanks for fixing this. We have been running a server at https://tests.stockfishchess.org/tests that almost reads like the description of the testcase in #418 (comment) and have seen this happen multiple times in the past, if the load on the server was high (with dropped connections by nginx / nginx reboots), almost on a daily basis (most recently discussed as official-stockfish/fishtest#2094 ... but we had no real clue). We'd be happy to upgrade waitress to an eventual 3.0.1 as mentioned in 3495674 . Is there a timeline for that (also in light of the green CI)? |
Bumps [waitress](https://github.com/Pylons/waitress) from 2.1.2 to 3.0.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/Pylons/waitress/releases">waitress's releases</a>.</em></p> <blockquote> <h2>v3.0.0</h2> <h1>3.0.0 (2024-02-04)</h1> <ul> <li> <p>Rename "master" git branch to "main"</p> </li> <li> <p>Fix a bug that would appear on macOS whereby if we accept() a socket that is already gone, setting socket options would fail and take down the server. See <a href="https://github.com/Pylons/waitress/pull/399">Pylons/waitress#399</a></p> </li> <li> <p>Fixed testing of vendored asyncore code to not rely on particular naming for errno's. See <a href="https://github.com/Pylons/waitress/pull/397">Pylons/waitress#397</a></p> </li> <li> <p>HTTP Request methods and versions are now validated to meet the HTTP standards thereby dropping invalid requests on the floor. See <a href="https://github.com/Pylons/waitress/pull/423">Pylons/waitress#423</a></p> </li> <li> <p>No longer close the connection when sending a HEAD request response. See <a href="https://github.com/Pylons/waitress/pull/428">Pylons/waitress#428</a></p> </li> <li> <p>Always attempt to send the Connection: close response header when we are going to close the connection to let the remote know in more instances. <a href="https://github.com/Pylons/waitress/pull/429">Pylons/waitress#429</a></p> </li> <li> <p>Python 3.7 is no longer supported. Add support for Python 3.11, 3.12 and PyPy 3.9, 3.10. See <a href="https://github.com/Pylons/waitress/pull/412">Pylons/waitress#412</a></p> </li> <li> <p>Document that trusted_proxy may be set to a wildcard value to trust all proxies. See <a href="https://github.com/Pylons/waitress/pull/431">Pylons/waitress#431</a></p> </li> </ul> <h2>Updated Defaults</h2> <ul> <li>clear_untrusted_proxy_headers is set to True by default. See <a href="https://github.com/Pylons/waitress/pull/370">Pylons/waitress#370</a></li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/Pylons/waitress/blob/main/CHANGES.txt">waitress's changelog</a>.</em></p> <blockquote> <h2>3.0.1 (2024-11-28)</h2> <p>Security</p> <pre><code> - Fix a bug that would lead to Waitress busy looping on select() on a half-open socket due to a race condition that existed when creating a new HTTPChannel. See Pylons/waitress#435, Pylons/waitress#418 and GHSA-3f84-rpwh-47g6 <p>With thanks to Dylan Jay and Dieter Maurer for their extensive debugging and<br /> helping track this down.</p> <ul> <li> <p>No longer strip the header values before passing them to the WSGI environ.<br /> See <a href="https://github.com/Pylons/waitress/pull/434">Pylons/waitress#434</a> and<br /> <a href="https://github.com/Pylons/waitress/issues/432">Pylons/waitress#432</a></p> </li> <li> <p>Fix a race condition in Waitress when <code>channel_request_lookahead</code> is enabled<br /> that could lead to HTTP request smuggling.</p> <p>See <a href="https://github.com/Pylons/waitress/security/advisories/GHSA-9298-4cf8-g4wj">https://github.com/Pylons/waitress/security/advisories/GHSA-9298-4cf8-g4wj</a></p> </li> </ul> <h2>3.0.0 (2024-02-04)</h2> <ul> <li> <p>Rename "master" git branch to "main"</p> </li> <li> <p>Fix a bug that would appear on macOS whereby if we accept() a socket that is<br /> already gone, setting socket options would fail and take down the server. See<br /> <a href="https://github.com/Pylons/waitress/pull/399">Pylons/waitress#399</a></p> </li> <li> <p>Fixed testing of vendored asyncore code to not rely on particular naming for<br /> errno's. See <a href="https://github.com/Pylons/waitress/pull/397">Pylons/waitress#397</a></p> </li> <li> <p>HTTP Request methods and versions are now validated to meet the HTTP<br /> standards thereby dropping invalid requests on the floor. See<br /> <a href="https://github.com/Pylons/waitress/pull/423">Pylons/waitress#423</a></p> </li> <li> <p>No longer close the connection when sending a HEAD request response. See<br /> <a href="https://github.com/Pylons/waitress/pull/428">Pylons/waitress#428</a></p> </li> <li> <p>Always attempt to send the Connection: close response header when we are<br /> going to close the connection to let the remote know in more instances.<br /> <a href="https://github.com/Pylons/waitress/pull/429">Pylons/waitress#429</a></p> </li> <li> <p>Python 3.7 is no longer supported. Add support for Python 3.11, 3.12 and<br /> PyPy 3.9, 3.10. See <a href="https://github.com/Pylons/waitress/pull/412">Pylons/waitress#412</a></p> </li> </ul> <p></tr></table><br /> </code></pre></p> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/Pylons/waitress/commit/ae949bb428e50cf04152db56460f31c1e6d3a2a9"><code>ae949bb</code></a> Ready for 3.0.1</li> <li><a href="https://github.com/Pylons/waitress/commit/e4359018537af376cf24bd13616d861e2fb76f65"><code>e435901</code></a> Merge commit from fork</li> <li><a href="https://github.com/Pylons/waitress/commit/810a435f9e9e293bd3446a5ce2df86f59c4e7b1b"><code>810a435</code></a> Add documentation for channel_request_lookahead</li> <li><a href="https://github.com/Pylons/waitress/commit/f4ba1c260cf17156b582c6252496213ddc96b591"><code>f4ba1c2</code></a> Fix a race condition on recv_bytes boundary when request is invalid</li> <li><a href="https://github.com/Pylons/waitress/commit/7e7f11e61d358ab1cb853fcadf2b46b1f00f5993"><code>7e7f11e</code></a> Add a new test to validate the lookahead race condition</li> <li><a href="https://github.com/Pylons/waitress/commit/6943dcf556610ece2ff3cddb39e59a05ef110661"><code>6943dcf</code></a> Make DummySock() look more like an actual socket</li> <li><a href="https://github.com/Pylons/waitress/commit/fdd2ecfd325af2f419d91c62b2551e2c3922f686"><code>fdd2ecf</code></a> Merge pull request <a href="https://github.com/Pylons/waitress/issues/445">#445</a> from Pylons/feature/support-py-3-13</li> <li><a href="https://github.com/Pylons/waitress/commit/dcd18e7b4b8e78e2abea8f286c23b0b9298bea9b"><code>dcd18e7</code></a> Update exclude matrix</li> <li><a href="https://github.com/Pylons/waitress/commit/4633ea6d69d6b7eff5db91e263ea85f437026db0"><code>4633ea6</code></a> Drop Python 3.8 and add Python 3.13</li> <li><a href="https://github.com/Pylons/waitress/commit/4584936eac5838b6d3b07e84a86874fa586ffe6e"><code>4584936</code></a> Merge pull request <a href="https://github.com/Pylons/waitress/issues/440">#440</a> from Pylons/fix/ci</li> <li>Additional commits viewable in <a href="https://github.com/Pylons/waitress/compare/v2.1.2...v3.0.1">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=waitress&package-manager=pip&previous-version=2.1.2&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/uktrade/jml/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
When we
accept()
a connection we get the remote address and we pass it toHTTPChannel
, then inwasyncore.dispatcher
we were callinggetpeername()
again to get the same remote address that we already had.This would cause an issue if the remote client had sent data, but closed the connection before
getpeername()
because thewasyncore.dispatcher
would set the channel to no longer being connected.Further down the line this would cause issues whereby
handle_write
would loop over and over because it would mark itself as selectable but the socket would never actually get torn down.Closes #418
Supersedes #419