File CVE-2020-11080.patch of Package nodejs8.18412
commit 881c244a4e1b857d883cd105cd035a1fd6ed3fa6
Author: James M Snell <jasnell@gmail.com>
Date: Mon Apr 27 10:47:58 2020 -0700
http2: implement support for max settings entries
Adds the maxSettings option to limit the number of settings
entries allowed per SETTINGS frame. Default 32
Signed-off-by: James M Snell <jasnell@gmail.com>
Fixes: https://hackerone.com/reports/446662
CVE-ID: CVE-2020-11080
PR-URL: https://github.com/nodejs-private/node-private/pull/204
Backport-PR-URL: https://github.com/nodejs-private/node-private/pull/207
Reviewed-By: Beth Griggs <Bethany.Griggs@uk.ibm.com>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Index: node-v8.17.0/doc/api/http2.md
===================================================================
--- node-v8.17.0.orig/doc/api/http2.md
+++ node-v8.17.0/doc/api/http2.md
@@ -1885,6 +1885,9 @@ error will be thrown.
<!-- YAML
added: v8.4.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs-private/node-private/pull/204
+ description: Added `maxSettings` option with a default of 32.
- version: v8.9.3
pr-url: https://github.com/nodejs/node/pull/17105
description: Added the `maxOutstandingPings` option with a default limit of
@@ -1902,6 +1905,8 @@ changes:
* `options` {Object}
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
for deflating header fields. **Default:** `4Kib`.
+ * `maxSettings` {number} Sets the maximum number of settings entries per
+ `SETTINGS` frame. The minimum value allowed is `1`. **Default:** `32`.
* `maxSessionMemory`{number} Sets the maximum memory that the `Http2Session`
is permitted to use. The value is expressed in terms of number of megabytes,
e.g. `1` equal 1 megabyte. The minimum value allowed is `1`.
@@ -1995,6 +2000,9 @@ server.listen(80);
<!-- YAML
added: v8.4.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs-private/node-private/pull/204
+ description: Added `maxSettings` option with a default of 32.
- version: v8.13.0
pr-url: https://github.com/nodejs/node/pull/22956
description: Added the `origins` option to automatically send an `ORIGIN`
@@ -2016,6 +2024,8 @@ changes:
**Default:** `false`.
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
for deflating header fields. **Default:** `4Kib`.
+ * `maxSettings` {number} Sets the maximum number of settings entries per
+ `SETTINGS` frame. The minimum value allowed is `1`. **Default:** `32`.
* `maxSessionMemory`{number} Sets the maximum memory that the `Http2Session`
is permitted to use. The value is expressed in terms of number of megabytes,
e.g. `1` equal 1 megabyte. The minimum value allowed is `1`. This is a
@@ -2097,6 +2107,9 @@ server.listen(80);
<!-- YAML
added: v8.4.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs-private/node-private/pull/204
+ description: Added `maxSettings` option with a default of 32.
- version: v8.9.3
pr-url: https://github.com/nodejs/node/pull/17105
description: Added the `maxOutstandingPings` option with a default limit of
@@ -2111,6 +2124,8 @@ changes:
* `options` {Object}
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
for deflating header fields. **Default:** `4Kib`.
+ * `maxSettings` {number} Sets the maximum number of settings entries per
+ `SETTINGS` frame. The minimum value allowed is `1`. **Default:** `32`.
* `maxSessionMemory`{number} Sets the maximum memory that the `Http2Session`
is permitted to use. The value is expressed in terms of number of megabytes,
e.g. `1` equal 1 megabyte. The minimum value allowed is `1`.
Index: node-v8.17.0/lib/internal/http2/util.js
===================================================================
--- node-v8.17.0.orig/lib/internal/http2/util.js
+++ node-v8.17.0/lib/internal/http2/util.js
@@ -176,7 +176,8 @@ const IDX_OPTIONS_MAX_HEADER_LIST_PAIRS
const IDX_OPTIONS_MAX_OUTSTANDING_PINGS = 6;
const IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS = 7;
const IDX_OPTIONS_MAX_SESSION_MEMORY = 8;
-const IDX_OPTIONS_FLAGS = 9;
+const IDX_OPTIONS_MAX_SETTINGS = 9;
+const IDX_OPTIONS_FLAGS = 10;
function updateOptionsBuffer(options) {
var flags = 0;
@@ -225,6 +226,11 @@ function updateOptionsBuffer(options) {
optionsBuffer[IDX_OPTIONS_MAX_SESSION_MEMORY] =
Math.max(1, options.maxSessionMemory);
}
+ if (typeof options.maxSettings === 'number') {
+ flags |= (1 << IDX_OPTIONS_MAX_SETTINGS);
+ optionsBuffer[IDX_OPTIONS_MAX_SETTINGS] =
+ Math.max(1, options.maxSettings);
+ }
optionsBuffer[IDX_OPTIONS_FLAGS] = flags;
}
Index: node-v8.17.0/src/node_http2.cc
===================================================================
--- node-v8.17.0.orig/src/node_http2.cc
+++ node-v8.17.0/src/node_http2.cc
@@ -195,6 +195,12 @@ Http2Options::Http2Options(Environment*
if (flags & (1 << IDX_OPTIONS_MAX_SESSION_MEMORY)) {
SetMaxSessionMemory(buffer[IDX_OPTIONS_MAX_SESSION_MEMORY] * 1e6);
}
+
+ if (flags & (1 << IDX_OPTIONS_MAX_SETTINGS)) {
+ nghttp2_option_set_max_settings(
+ options_,
+ static_cast<size_t>(buffer[IDX_OPTIONS_MAX_SETTINGS]));
+ }
}
void Http2Session::Http2Settings::Init() {
Index: node-v8.17.0/src/node_http2_state.h
===================================================================
--- node-v8.17.0.orig/src/node_http2_state.h
+++ node-v8.17.0/src/node_http2_state.h
@@ -51,6 +51,7 @@ namespace http2 {
IDX_OPTIONS_MAX_OUTSTANDING_PINGS,
IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS,
IDX_OPTIONS_MAX_SESSION_MEMORY,
+ IDX_OPTIONS_MAX_SETTINGS,
IDX_OPTIONS_FLAGS
};
Index: node-v8.17.0/test/parallel/test-http2-max-settings.js
===================================================================
--- /dev/null
+++ node-v8.17.0/test/parallel/test-http2-max-settings.js
@@ -0,0 +1,35 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const http2 = require('http2');
+
+const server = http2.createServer({ maxSettings: 1 });
+
+// TODO(@jasnell): There is still a session event
+// emitted on the server side but it will be destroyed
+// immediately after creation and there will be no
+// stream created.
+server.on('session', common.mustCall((session) => {
+ session.on('stream', common.mustNotCall());
+ session.on('remoteSettings', common.mustNotCall());
+}));
+server.on('stream', common.mustNotCall());
+
+server.listen(0, common.mustCall(() => {
+ // Specify two settings entries when a max of 1 is allowed.
+ // Connection should error immediately.
+ const client = http2.connect(
+ `http://localhost:${server.address().port}`, {
+ settings: {
+ // The actual settings values do not matter.
+ headerTableSize: 1000,
+ enablePush: false,
+ } });
+
+ client.on('error', common.mustCall(() => {
+ server.close();
+ }));
+}));
Index: node-v8.17.0/test/parallel/test-http2-util-update-options-buffer.js
===================================================================
--- node-v8.17.0.orig/test/parallel/test-http2-util-update-options-buffer.js
+++ node-v8.17.0/test/parallel/test-http2-util-update-options-buffer.js
@@ -21,7 +21,8 @@ const IDX_OPTIONS_MAX_HEADER_LIST_PAIRS
const IDX_OPTIONS_MAX_OUTSTANDING_PINGS = 6;
const IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS = 7;
const IDX_OPTIONS_MAX_SESSION_MEMORY = 8;
-const IDX_OPTIONS_FLAGS = 9;
+const IDX_OPTIONS_MAX_SETTINGS = 9;
+const IDX_OPTIONS_FLAGS = 10;
{
updateOptionsBuffer({
@@ -33,7 +34,8 @@ const IDX_OPTIONS_FLAGS = 9;
maxHeaderListPairs: 6,
maxOutstandingPings: 7,
maxOutstandingSettings: 8,
- maxSessionMemory: 9
+ maxSessionMemory: 9,
+ maxSettings: 10,
});
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE], 1);
@@ -45,6 +47,7 @@ const IDX_OPTIONS_FLAGS = 9;
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_PINGS], 7);
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS], 8);
strictEqual(optionsBuffer[IDX_OPTIONS_MAX_SESSION_MEMORY], 9);
+ strictEqual(optionsBuffer[IDX_OPTIONS_MAX_SETTINGS], 10);
const flags = optionsBuffer[IDX_OPTIONS_FLAGS];
@@ -56,6 +59,7 @@ const IDX_OPTIONS_FLAGS = 9;
ok(flags & (1 << IDX_OPTIONS_MAX_HEADER_LIST_PAIRS));
ok(flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_PINGS));
ok(flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS));
+ ok(flags & (1 << IDX_OPTIONS_MAX_SETTINGS));
}
{