Skip to content
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

http2: fix double free due to handling of rst_stream with cancel code #39423

Closed
wants to merge 2 commits into from

Conversation

kumarak
Copy link
Contributor

@kumarak kumarak commented Jul 18, 2021

The PR changes add the stream to the pending list on receiving
RST_STREAM frame with error code nghttp2_cancel. This is to
avoid the force purging of data on receiving the rst_stream frame.

On force purging, the nghttp2 raises close callback for already
destroyed stream which is causing the double-free memory error.

Fixes: #38964

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. http2 Issues or PRs related to the http2 subsystem. needs-ci PRs that need a full CI run. labels Jul 18, 2021
@kumarak kumarak changed the title http2: fix double free due to handle of RST_STREAM http2: fix double free due to handling of RST_STREAM with cancel code Jul 18, 2021
@kumarak kumarak changed the title http2: fix double free due to handling of RST_STREAM with cancel code http2: fix double free due to handling of rst_stream Jul 18, 2021
@kumarak kumarak changed the title http2: fix double free due to handling of rst_stream http2: fix double free due to handling of rst_stream with cancel code Jul 18, 2021
http2: add checks to update the pending list if stream received in scope
@kumarak
Copy link
Contributor Author

kumarak commented Jul 19, 2021

I updated the conditions to add streams to the pending list on receiving RST_STREAM frame. Looking into the failing test cases, I found the RST_STREAM frames may get received when the session is not in scope. Adding streams to the pending list in such cases causes the endpoint to hang. The check prevents it. There could be other possible cases where the pending streams may not get processed and I may have missed handling it. It will be great to get feedback from the community on this.

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@nodejs-github-bot
Copy link
Collaborator

@mcollina mcollina added lts-watch-v12.x commit-queue Add this label to land a pull request using GitHub Actions. labels Jul 20, 2021
@github-actions github-actions bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Jul 20, 2021
@github-actions
Copy link
Contributor

Commit Queue failed
- Loading data for nodejs/node/pull/39423
✔  Done loading data for nodejs/node/pull/39423
----------------------------------- PR info ------------------------------------
Title      http2: fix double free due to handling of rst_stream with cancel code (#39423)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     kumarak:kumarak/fix_38964 -> nodejs:master
Labels     c++, commit-queue, http2, lts-watch-v12.x, lts-watch-v14.x, needs-ci
Commits    2
 - http2: on receiving rst_stream with cancel code add it to pending list
 - http2: update checks for adding rst_stream to pending list
Committers 1
 - Akshay K 
PR-URL: https://github.com/nodejs/node/pull/39423
Fixes: https://github.com/nodejs/node/issues/38964
Reviewed-By: James M Snell 
Reviewed-By: Matteo Collina 
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/39423
Fixes: https://github.com/nodejs/node/issues/38964
Reviewed-By: James M Snell 
Reviewed-By: Matteo Collina 
--------------------------------------------------------------------------------
   ℹ  This PR was created on Sun, 18 Jul 2021 02:26:43 GMT
   ✔  Approvals: 2
   ✔  - James M Snell (@jasnell) (TSC): https://github.com/nodejs/node/pull/39423#pullrequestreview-709620997
   ✔  - Matteo Collina (@mcollina) (TSC): https://github.com/nodejs/node/pull/39423#pullrequestreview-710283289
   ✖  Last GitHub CI failed
   ℹ  Last Full PR CI on 2021-07-20T07:57:13Z: https://ci.nodejs.org/job/node-test-pull-request/39151/
- Querying data for job/node-test-pull-request/39151/
✔  Build data downloaded
   ✔  Last Jenkins CI successful
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/1048570186

@mcollina
Copy link
Member

Landed in c0f1000

@mcollina mcollina closed this Jul 20, 2021
mcollina pushed a commit that referenced this pull request Jul 20, 2021
PR-URL: #39423
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
targos pushed a commit that referenced this pull request Jul 20, 2021
PR-URL: #39423
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
richardlau pushed a commit that referenced this pull request Jul 23, 2021
PR-URL: #39423
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@richardlau
Copy link
Member

This cherry-picks to v12.x-staging without conflicts but doesn't compile:

../src/node_http2.cc: In member function ‘void node::http2::Http2Stream::SubmitRstStream(uint32_t)’:
../src/node_http2.cc:2165:17: error: ‘class node::http2::Http2Session’ has no member named ‘is_in_scope’
   if (session_->is_in_scope() &&
                 ^~~~~~~~~~~
../src/node_http2.cc:2166:20: error: ‘is_writable’ was not declared in this scope
      !is_writable() && is_reading()) {
                    ^
../src/node_http2.cc:2166:36: error: ‘is_reading’ was not declared in this scope
       !is_writable() && is_reading()) {
                                    ^

@kumarak
Copy link
Contributor Author

kumarak commented Jul 23, 2021

Thanks, @richardlau for the notification. I will check the compile issue with v12.x-staging.

richardlau pushed a commit that referenced this pull request Jul 23, 2021
PR-URL: #39423
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@richardlau richardlau mentioned this pull request Jul 23, 2021
@richardlau
Copy link
Member

FWIW I tried this on v12.x-staging, which compiled but ended up with two http2 tests timing out

diff --git a/src/node_http2.cc b/src/node_http2.cc
index dec6d7dab9..46b7dbf80e 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -2150,6 +2150,25 @@ int Http2Stream::SubmitPriority(nghttp2_priority_spec* prispec,
 void Http2Stream::SubmitRstStream(const uint32_t code) {
   CHECK(!this->IsDestroyed());
   code_ = code;
+
+  // If RST_STREAM frame is received and stream is not writable
+  // because it is busy reading data, don't try force purging it.
+  // Instead add the stream to pending stream list and process
+  // the pending data when it is safe to do so. This is to avoid
+  // double free error due to unwanted behavior of nghttp2.
+  // Ref:https://github.com/nodejs/node/issues/38964
+
+  // Add stream to the pending list if it is received with scope
+  // below in the stack. The pending list may not get processed
+  // if RST_STREAM received is not in scope and added to the list
+  // causing endpoint to hang.
+  if ((flags_ & SESSION_STATE_HAS_SCOPE) &&
+      !IsWritable() && IsReading()) {
+    session_->AddPendingRstStream(id_);
+    return;
+  }
+
+
   // If possible, force a purge of any currently pending data here to make sure
   // it is sent before closing the stream. If it returns non-zero then we need
   // to wait until the current write finishes and try again to avoid nghttp2
=== release test-http2-server-shutdown-options-errors ===
Path: parallel/test-http2-server-shutdown-options-errors
Command: out/Release/node /home/iojs/node-tree/v12.x/test/parallel/test-http2-server-shutdown-options-errors.js
--- TIMEOUT ---
=== release test-http2-server-stream-session-destroy ===
Path: parallel/test-http2-server-stream-session-destroy
Command: out/Release/node /home/iojs/node-tree/v12.x/test/parallel/test-http2-server-stream-session-destroy.js
--- TIMEOUT ---
[06:27|% 100|+ 3038|-   2]: Done

cc @nodejs/http2

@kumarak
Copy link
Contributor Author

kumarak commented Jul 26, 2021

Hi @richardlau, there is no concept of scope with Http2Stream. The flags_ from Http2Session should be exposed and tested if it is set to SESSION_STATE_HAS_SCOPE.

Can I raise a PR specifically with v12.x-staging branch?

@richardlau
Copy link
Member

Yes, please raise a PR targeting the v12.x-staging branch.

@BethGriggs BethGriggs mentioned this pull request Jul 26, 2021
richardlau pushed a commit that referenced this pull request Jul 27, 2021
PR-URL: #39423
Backport-PR-URL: #39527
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
richardlau pushed a commit that referenced this pull request Jul 27, 2021
PR-URL: #39423
Backport-PR-URL: #39527
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@richardlau richardlau mentioned this pull request Jul 27, 2021
richardlau pushed a commit that referenced this pull request Jul 28, 2021
PR-URL: #39423
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
BethGriggs pushed a commit that referenced this pull request Jul 29, 2021
PR-URL: #39423
Fixes: #38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
BethGriggs added a commit that referenced this pull request Jul 29, 2021
This is a security release.

Notable Changes:

- CVE-2021-22930: Use after free on close http2 on stream canceling
  (High) [#39423](#39423)
- (SEMVER-MINOR) deps: update V8 to 9.2.230.21 (Michaël Zasso)
  [#39470](#39470)
- inspector: mark as stable (Gireesh Punathil)
  [#37748](#37748)
- (SEMVER-MINOR) perf_hooks: web performance timeline compliance
  (legendecas) [#39297](#39297)
- punycode: add pending deprecation (Antoine du Hamel)
  [#38444](#38444)
- (SEMVER-MINOR) repl: enable --experimental-repl-await /w opt-out
  (hemanth.hm) [#34733](#34733)

PR-URL: #39534
BethGriggs added a commit that referenced this pull request Jul 29, 2021
This is a security release.

Notable Changes:

- CVE-2021-22930: Use after free on close http2 on stream canceling
  (High) [#39423](#39423)
- (SEMVER-MINOR) deps: update V8 to 9.2.230.21 (Michaël Zasso)
  [#39470](#39470)
- inspector: mark as stable (Gireesh Punathil)
  [#37748](#37748)
- (SEMVER-MINOR) perf_hooks: web performance timeline compliance
  (legendecas) [#39297](#39297)
- punycode: add pending deprecation (Antoine du Hamel)
  [#38444](#38444)
- (SEMVER-MINOR) repl: enable --experimental-repl-await /w opt-out
  (hemanth.hm) [#34733](#34733)

PR-URL: #39534
BethGriggs added a commit that referenced this pull request Jul 29, 2021
This is a security release.

Notable Changes:

- CVE-2021-22930: Use after free on close http2 on stream canceling
  (High) [#39423](#39423)
- (SEMVER-MINOR) deps: update V8 to 9.2.230.21 (Michaël Zasso)
  [#39470](#39470)
- inspector: mark as stable (Gireesh Punathil)
  [#37748](#37748)
- punycode: add pending deprecation (Antoine du Hamel)
  [#38444](#38444)
- (SEMVER-MINOR) repl: enable --experimental-repl-await /w opt-out
  (hemanth.hm) [#34733](#34733)

PR-URL: #39534
BethGriggs added a commit that referenced this pull request Jul 29, 2021
This is a security release.

Notable Changes:

- CVE-2021-22930: Use after free on close http2 on stream canceling
  (High) [#39423](#39423)
- (SEMVER-MINOR) deps: update V8 to 9.2.230.21 (Michaël Zasso)
  [#39470](#39470)
- inspector: mark as stable (Gireesh Punathil)
  [#37748](#37748)
- punycode: add pending deprecation (Antoine du Hamel)
  [#38444](#38444)
- (SEMVER-MINOR) repl: enable --experimental-repl-await /w opt-out
  (hemanth.hm) [#34733](#34733)

PR-URL: #39534
BethGriggs pushed a commit that referenced this pull request Aug 6, 2021
The PR updates the handling of rst_stream frames and adds all streams
to the pending list on receiving rst frames with the error code
NGHTTP2_CANCEL.

The changes will remove dependency on the stream state that may allow
bypassing the checks in certain cases. I think a better solution is to
delay streams in all cases if rst_stream is received for the cancel
events.

The rst_stream frames can be received for protocol/connection error as
well it should be handled immediately. Adding streams to the pending
list in such cases may cause errors.

PR-URL: #39622
Refs: #39423
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
BethGriggs pushed a commit that referenced this pull request Aug 6, 2021
PR-URL: #39622
Refs: #39423
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
@targos targos removed the commit-queue-failed An error occurred while landing this pull request using GitHub Actions. label Sep 5, 2021
foxxyz pushed a commit to foxxyz/node that referenced this pull request Oct 18, 2021
PR-URL: nodejs#39423
Fixes: nodejs#38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
foxxyz pushed a commit to foxxyz/node that referenced this pull request Oct 18, 2021
The PR updates the handling of rst_stream frames and adds all streams
to the pending list on receiving rst frames with the error code
NGHTTP2_CANCEL.

The changes will remove dependency on the stream state that may allow
bypassing the checks in certain cases. I think a better solution is to
delay streams in all cases if rst_stream is received for the cancel
events.

The rst_stream frames can be received for protocol/connection error as
well it should be handled immediately. Adding streams to the pending
list in such cases may cause errors.

CVE-ID: CVE-2021-22930
Refs: https://nvd.nist.gov/vuln/detail/CVE-2021-22930
PR-URL: nodejs#39622
Refs: nodejs#39423
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
foxxyz pushed a commit to foxxyz/node that referenced this pull request Oct 18, 2021
PR-URL: nodejs#39622
Refs: nodejs#39423
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. http2 Issues or PRs related to the http2 subsystem. needs-ci PRs that need a full CI run.
Projects
None yet
6 participants