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: treat non-EOF empty frames like other invalid frames #37875

Closed
wants to merge 4 commits into from

Conversation

addaleax
Copy link
Member

http2: fix setting options before handle exists

Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the AliasedStruct
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

http2: treat non-EOF empty frames like other invalid frames

Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a flood of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

@nodejs/http2

Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. needs-ci PRs that need a full CI run. labels Mar 23, 2021
@addaleax addaleax added http2 Issues or PRs related to the http2 subsystem. lts-watch-v12.x and removed lib / src Issues and PRs related to general changes in the lib or src directory. labels Mar 23, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: nodejs#37849
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

nodejs-github-bot commented Mar 23, 2021

lib/internal/http2/core.js Outdated Show resolved Hide resolved
lib/internal/http2/core.js Outdated Show resolved Hide resolved
@@ -1335,7 +1335,11 @@ int Http2Session::HandleDataFrame(const nghttp2_frame* frame) {
frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream->EmitRead(UV_EOF);
} else if (frame->hd.length == 0) {
return 1; // Consider 0-length frame without END_STREAM an error.
if (invalid_frame_count_++ > js_fields_->max_invalid_frames) {

Choose a reason for hiding this comment

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

Should invalid_frame_count be reset if valid frames come through? Pertaining to #37849, if an end server is sending EOF frames after every valid frame, would this solution only allow for single requests in a session?

Copy link
Member Author

Choose a reason for hiding this comment

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

So... I don't think we'd want to reset after every valid frame, or at least I think that would be a bit separate from this PR.

What would makes sense to me is to make this a ratio of invalid frames/total frames that is being limited, rather than the total # of invalid frames ... but that feels a bit out of scope here :/ In any case, users who do wish to allow for a large number of invalid frames can set the maxSessionInvalidFrames option to a large value, if they are connecting to problematic servers.

@addaleax addaleax added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. and removed needs-ci PRs that need a full CI run. labels Mar 25, 2021
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented Mar 25, 2021

@addaleax
Copy link
Member Author

Landed in a9cdeed...87aa3f1

@addaleax addaleax closed this Mar 26, 2021
addaleax added a commit that referenced this pull request Mar 26, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
addaleax added a commit that referenced this pull request Mar 26, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
@addaleax addaleax deleted the 37849-dev branch March 26, 2021 19:52
ruyadorno pushed a commit that referenced this pull request Mar 29, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
ruyadorno pushed a commit that referenced this pull request Mar 29, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
ruyadorno pushed a commit that referenced this pull request Mar 30, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
ruyadorno pushed a commit that referenced this pull request Mar 30, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
@ruyadorno ruyadorno mentioned this pull request Mar 30, 2021
@danielleadams
Copy link
Contributor

@addaleax Do you mind opening up a backport PR for 14.x-staging? Thank you!

addaleax added a commit to addaleax/node that referenced this pull request May 13, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: nodejs#37875
Fixes: nodejs#37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
addaleax added a commit to addaleax/node that referenced this pull request May 13, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: nodejs#37849

PR-URL: nodejs#37875
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit to addaleax/node that referenced this pull request May 30, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: nodejs#37875
Fixes: nodejs#37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit to addaleax/node that referenced this pull request May 30, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: nodejs#37849

PR-URL: nodejs#37875
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit to addaleax/node that referenced this pull request Jun 5, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: nodejs#37875
Fixes: nodejs#37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit to addaleax/node that referenced this pull request Jun 5, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: nodejs#37849

PR-URL: nodejs#37875
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Backport-PR-URL: #38673
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Backport-PR-URL: #38673
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Backport-PR-URL: #38673
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Backport-PR-URL: #38673
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Backport-PR-URL: #38673
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Backport-PR-URL: #38673
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Backport-PR-URL: #38673
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 6, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Backport-PR-URL: #38673
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 11, 2021
Currently, when a JS Http2Session object is created, we have
to handle the situation in which the native object corresponding
to it does not yet exist. As part of that, we create a typed array
for storing options that are passed through the `AliasedStruct`
mechanism, and up until now, we copied that typed array over
the native one once the native one was available.

This was not good, because it was overwriting the defaults that
were set during construction of the native typed array with zeroes.

In order to fix this, create a wrapper for the JS-created typed array
that keeps track of which fields were changed, which enables us to
only overwrite fields that were intentionally changed on the JS side.

It is surprising that this behavior was not tested (which is,
guessing from the commit history around these features, my fault).
The subseqeuent commit introduces a test that would fail without
this change.

PR-URL: #37875
Backport-PR-URL: #38673
Fixes: #37849
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
targos pushed a commit that referenced this pull request Jun 11, 2021
Use the existing mechanism that we have to keep track of invalid frames
for treating this specific kind of invalid frame.

The commit that originally introduced this check was 695e38b,
which was supposed to proected against CVE-2019-9518, which in turn
was specifically about a *flood* of empty data frames. While these are
still invalid frames either way, it makes sense to be forgiving here
and just treat them like other invalid frames, i.e. to allow a small
(configurable) number of them.

Fixes: #37849

PR-URL: #37875
Backport-PR-URL: #38673
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
@richardlau
Copy link
Member

Doesn't land cleanly on v12.x-staging and would need a manual backport.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. c++ Issues and PRs that require attention from people who are familiar with C++. http2 Issues or PRs related to the http2 subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Http2 throws non-descriptive error "Error [ERR_HTTP2_ERROR]: The user callback function failed"
9 participants