Update to 12.22.11, fix some cves.

This commit is contained in:
wk333 2022-03-28 16:02:28 +08:00
parent 18d74738a4
commit 6472371bd3
12 changed files with 17 additions and 1049 deletions

View File

@ -1,25 +0,0 @@
From 7fddd1453f365e54b46f6564d5c168ed13e758db Mon Sep 17 00:00:00 2001
From: lingsheng <lingsheng@huawei.com>
Date: Wed, 18 Nov 2020 14:58:37 +0800
Subject: [PATCH] Modify openEuler aarch64 v8_os_page_size to 64
---
deps/v8/src/flags/flag-definitions.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deps/v8/src/flags/flag-definitions.h b/deps/v8/src/flags/flag-definitions.h
index c7c07e6d..38a035e2 100644
--- a/deps/v8/src/flags/flag-definitions.h
+++ b/deps/v8/src/flags/flag-definitions.h
@@ -917,7 +917,7 @@ DEFINE_BOOL(memory_reducer_for_small_heaps, true,
"use memory reducer for small heaps")
DEFINE_INT(heap_growing_percent, 0,
"specifies heap growing factor as (1 + heap_growing_percent/100)")
-DEFINE_INT(v8_os_page_size, 0, "override OS page size (in KBytes)")
+DEFINE_INT(v8_os_page_size, 64, "override OS page size (in KBytes)")
DEFINE_BOOL(always_compact, false, "Perform compaction on every full GC")
DEFINE_BOOL(never_compact, false,
"Never perform compaction on full GC - testing only")
--
2.23.0

View File

@ -1,164 +0,0 @@
From 5b00de7d67a1372aa342115ad28edd3f78268bb6 Mon Sep 17 00:00:00 2001
From: James M Snell <jasnell@gmail.com>
Date: Thu, 12 Nov 2020 12:34:33 -0800
Subject: [PATCH] src: retain pointers to WriteWrap/ShutdownWrap
Avoids potential use-after-free when wrap req's are synchronously
destroyed.
CVE-ID: CVE-2020-8265
Fixes: https://github.com/nodejs-private/node-private/issues/227
PR-URL: https://github.com/nodejs-private/node-private/pull/230
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=988103
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reference: https://github.com/nodejs/node/commit/5b00de7d67a1372aa342115ad28edd3f78268bb6
---
src/stream_base-inl.h | 11 +++-
src/stream_base.cc | 2 +-
src/stream_base.h | 1 +
.../test-tls-use-after-free-regression.js | 58 +++++++++++++++++++
4 files changed, 68 insertions(+), 4 deletions(-)
create mode 100644 test/parallel/test-tls-use-after-free-regression.js
diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h
index dd80683af10..1603a2fb2e0 100644
--- a/src/stream_base-inl.h
+++ b/src/stream_base-inl.h
@@ -163,8 +163,11 @@ inline int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
StreamReq::ResetObject(req_wrap_obj);
}
+ BaseObjectPtr<AsyncWrap> req_wrap_ptr;
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj);
+ if (req_wrap != nullptr)
+ req_wrap_ptr.reset(req_wrap->GetAsyncWrap());
int err = DoShutdown(req_wrap);
if (err != 0 && req_wrap != nullptr) {
@@ -198,7 +201,7 @@ inline StreamWriteResult StreamBase::Write(
if (send_handle == nullptr) {
err = DoTryWrite(&bufs, &count);
if (err != 0 || count == 0) {
- return StreamWriteResult { false, err, nullptr, total_bytes };
+ return StreamWriteResult { false, err, nullptr, total_bytes, {} };
}
}
@@ -208,13 +211,14 @@ inline StreamWriteResult StreamBase::Write(
if (!env->write_wrap_template()
->NewInstance(env->context())
.ToLocal(&req_wrap_obj)) {
- return StreamWriteResult { false, UV_EBUSY, nullptr, 0 };
+ return StreamWriteResult { false, UV_EBUSY, nullptr, 0, {} };
}
StreamReq::ResetObject(req_wrap_obj);
}
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
WriteWrap* req_wrap = CreateWriteWrap(req_wrap_obj);
+ BaseObjectPtr<AsyncWrap> req_wrap_ptr(req_wrap->GetAsyncWrap());
err = DoWrite(req_wrap, bufs, count, send_handle);
bool async = err == 0;
@@ -232,7 +236,8 @@ inline StreamWriteResult StreamBase::Write(
ClearError();
}
- return StreamWriteResult { async, err, req_wrap, total_bytes };
+ return StreamWriteResult {
+ async, err, req_wrap, total_bytes, std::move(req_wrap_ptr) };
}
template <typename OtherBase>
diff --git a/src/stream_base.cc b/src/stream_base.cc
index 516f57e40bf..06032e2c096 100644
--- a/src/stream_base.cc
+++ b/src/stream_base.cc
@@ -259,7 +259,7 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
// Immediate failure or success
if (err != 0 || count == 0) {
- SetWriteResult(StreamWriteResult { false, err, nullptr, data_size });
+ SetWriteResult(StreamWriteResult { false, err, nullptr, data_size, {} });
return err;
}
diff --git a/src/stream_base.h b/src/stream_base.h
index eb75fdc8339..fafd327d75d 100644
--- a/src/stream_base.h
+++ b/src/stream_base.h
@@ -24,6 +24,7 @@ struct StreamWriteResult {
int err;
WriteWrap* wrap;
size_t bytes;
+ BaseObjectPtr<AsyncWrap> wrap_obj;
};
using JSMethodFunction = void(const v8::FunctionCallbackInfo<v8::Value>& args);
diff --git a/test/parallel/test-tls-use-after-free-regression.js b/test/parallel/test-tls-use-after-free-regression.js
new file mode 100644
index 00000000000..51835fc0339
--- /dev/null
+++ b/test/parallel/test-tls-use-after-free-regression.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const common = require('../common');
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const https = require('https');
+const tls = require('tls');
+
+const kMessage =
+ 'GET / HTTP/1.1\r\nHost: localhost\r\nConnection: Keep-alive\r\n\r\n';
+
+const key = `-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIDKfHHbiJMdu2STyHL11fWC7psMY19/gUNpsUpkwgGACoAoGCCqGSM49
+AwEHoUQDQgAEItqm+pYj3Ca8bi5mBs+H8xSMxuW2JNn4I+kw3aREsetLk8pn3o81
+PWBiTdSZrGBGQSy+UAlQvYeE6Z/QXQk8aw==
+-----END EC PRIVATE KEY-----`;
+
+const cert = `-----BEGIN CERTIFICATE-----
+MIIBhjCCASsCFDJU1tCo88NYU//pE+DQKO9hUDsFMAoGCCqGSM49BAMCMEUxCzAJ
+BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
+dCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAwOTIyMDg1NDU5WhcNNDgwMjA3MDg1NDU5
+WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwY
+SW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
+QgAEItqm+pYj3Ca8bi5mBs+H8xSMxuW2JNn4I+kw3aREsetLk8pn3o81PWBiTdSZ
+rGBGQSy+UAlQvYeE6Z/QXQk8azAKBggqhkjOPQQDAgNJADBGAiEA7Bdn4F87KqIe
+Y/ABy/XIXXpFUb2nyv3zV7POQi2lPcECIQC3UWLmfiedpiIKsf9YRIyO0uEood7+
+glj2R1NNr1X68w==
+-----END CERTIFICATE-----`;
+
+const server = https.createServer(
+ { key, cert },
+ common.mustCall((req, res) => {
+ res.writeHead(200);
+ res.end('boom goes the dynamite\n');
+ }, 3));
+
+server.listen(0, common.mustCall(() => {
+ const socket =
+ tls.connect(
+ server.address().port,
+ 'localhost',
+ { rejectUnauthorized: false },
+ common.mustCall(() => {
+ socket.write(kMessage);
+ socket.write(kMessage);
+ socket.write(kMessage);
+ }));
+
+ socket.on('data', common.mustCall(() => socket.destroy()));
+ socket.on('close', () => {
+ setImmediate(() => server.close());
+ });
+}));

View File

@ -1,79 +0,0 @@
From 92d430917a63a567bb528100371263c46e50ee4a Mon Sep 17 00:00:00 2001
From: Fedor Indutny <fedor@indutny.com>
Date: Wed, 18 Nov 2020 20:50:21 -0800
Subject: [PATCH] http: unset `F_CHUNKED` on new `Transfer-Encoding`
Duplicate `Transfer-Encoding` header should be a treated as a single,
but with original header values concatenated with a comma separator. In
the light of this, even if the past `Transfer-Encoding` ended with
`chunked`, we should be not let the `F_CHUNKED` to leak into the next
header, because mere presence of another header indicates that `chunked`
is not the last transfer-encoding token.
CVE-ID: CVE-2020-8287
PR-URL: https://github.com/nodejs-private/node-private/pull/236
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reference: https://github.com/nodejs/node/commit/92d430917a63a567bb528100371263c46e50ee4a
---
deps/http_parser/http_parser.c | 7 +++++++
deps/http_parser/test.c | 26 ++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c
index 0f76b6a..5cc951a 100644
--- a/deps/http_parser/http_parser.c
+++ b/deps/http_parser/http_parser.c
@@ -1339,6 +1339,13 @@ reexecute:
} else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
parser->header_state = h_transfer_encoding;
parser->flags |= F_TRANSFER_ENCODING;
+
+ /* Multiple `Transfer-Encoding` headers should be treated as
+ * one, but with values separate by a comma.
+ *
+ * See: https://tools.ietf.org/html/rfc7230#section-3.2.2
+ */
+ parser->flags &= ~F_CHUNKED;
}
break;
diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c
index c979467..f185c56 100644
--- a/deps/http_parser/test.c
+++ b/deps/http_parser/test.c
@@ -2045,6 +2045,32 @@ const struct message responses[] =
,.body= "2\r\nOK\r\n0\r\n\r\n"
,.num_chunks_complete= 0
}
+#define HTTP_200_DUPLICATE_TE_NOT_LAST_CHUNKED 30
+, {.name= "HTTP 200 response with `chunked` and duplicate Transfer-Encoding"
+ ,.type= HTTP_RESPONSE
+ ,.raw= "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "Transfer-Encoding: identity\r\n"
+ "\r\n"
+ "2\r\n"
+ "OK\r\n"
+ "0\r\n"
+ "\r\n"
+ ,.should_keep_alive= FALSE
+ ,.message_complete_on_eof= TRUE
+ ,.http_major= 1
+ ,.http_minor= 1
+ ,.status_code= 200
+ ,.response_status= "OK"
+ ,.content_length= -1
+ ,.num_headers= 2
+ ,.headers=
+ { { "Transfer-Encoding", "chunked" }
+ , { "Transfer-Encoding", "identity" }
+ }
+ ,.body= "2\r\nOK\r\n0\r\n\r\n"
+ ,.num_chunks_complete= 0
+ }
};
/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so
--
2.23.0

View File

@ -1,151 +0,0 @@
From 420244e4d9ca6de2612e7f503f5c87e448fbc14b Mon Sep 17 00:00:00 2001
From: Matteo Collina <hello@matteocollina.com>
Date: Thu, 22 Oct 2020 14:10:51 +0200
Subject: [PATCH] http: unset `F_CHUNKED` on new `Transfer-Encoding`
Duplicate `Transfer-Encoding` header should be a treated as a single,
but with original header values concatenated with a comma separator. In
the light of this, even if the past `Transfer-Encoding` ended with
`chunked`, we should be not let the `F_CHUNKED` to leak into the next
header, because mere presence of another header indicates that `chunked`
is not the last transfer-encoding token.
Ref: https://github.com/nodejs-private/llhttp-private/pull/3
See: https://hackerone.com/bugs?report_id=1002188&subject=nodejs
CVE-ID: CVE-2020-8287
PR-URL: https://github.com/nodejs-private/node-private/pull/236
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reference: https://github.com/nodejs/node/commit/420244e4d9ca6de2612e7f503f5c87e448fbc14b
---
deps/llhttp/src/llhttp.c | 36 ++++++++++++++-
.../test-http-transfer-encoding-smuggling.js | 46 +++++++++++++++++++
2 files changed, 80 insertions(+), 2 deletions(-)
create mode 100644 test/parallel/test-http-transfer-encoding-smuggling.js
diff --git a/deps/llhttp/src/llhttp.c b/deps/llhttp/src/llhttp.c
index acc35479f88..3019c410963 100644
--- a/deps/llhttp/src/llhttp.c
+++ b/deps/llhttp/src/llhttp.c
@@ -813,6 +813,14 @@ int llhttp__internal__c_or_flags_16(
return 0;
}
+int llhttp__internal__c_and_flags(
+ llhttp__internal_t* state,
+ const unsigned char* p,
+ const unsigned char* endp) {
+ state->flags &= -9;
+ return 0;
+}
+
int llhttp__internal__c_update_header_state_7(
llhttp__internal_t* state,
const unsigned char* p,
@@ -5974,10 +5982,18 @@ static llparse_state_t llhttp__internal__run(
/* UNREACHABLE */;
abort();
}
+ s_n_llhttp__internal__n_invoke_and_flags: {
+ switch (llhttp__internal__c_and_flags(state, p, endp)) {
+ default:
+ goto s_n_llhttp__internal__n_header_value_te_chunked;
+ }
+ /* UNREACHABLE */;
+ abort();
+ }
s_n_llhttp__internal__n_invoke_or_flags_16: {
switch (llhttp__internal__c_or_flags_16(state, p, endp)) {
default:
- goto s_n_llhttp__internal__n_header_value_te_chunked;
+ goto s_n_llhttp__internal__n_invoke_and_flags;
}
/* UNREACHABLE */;
abort();
@@ -7625,6 +7641,14 @@ int llhttp__internal__c_or_flags_16(
return 0;
}
+int llhttp__internal__c_and_flags(
+ llhttp__internal_t* state,
+ const unsigned char* p,
+ const unsigned char* endp) {
+ state->flags &= -9;
+ return 0;
+}
+
int llhttp__internal__c_update_header_state_7(
llhttp__internal_t* state,
const unsigned char* p,
@@ -12522,10 +12546,18 @@ static llparse_state_t llhttp__internal__run(
/* UNREACHABLE */;
abort();
}
+ s_n_llhttp__internal__n_invoke_and_flags: {
+ switch (llhttp__internal__c_and_flags(state, p, endp)) {
+ default:
+ goto s_n_llhttp__internal__n_header_value_te_chunked;
+ }
+ /* UNREACHABLE */;
+ abort();
+ }
s_n_llhttp__internal__n_invoke_or_flags_16: {
switch (llhttp__internal__c_or_flags_16(state, p, endp)) {
default:
- goto s_n_llhttp__internal__n_header_value_te_chunked;
+ goto s_n_llhttp__internal__n_invoke_and_flags;
}
/* UNREACHABLE */;
abort();
diff --git a/test/parallel/test-http-transfer-encoding-smuggling.js b/test/parallel/test-http-transfer-encoding-smuggling.js
new file mode 100644
index 00000000000..9d97db4c0a2
--- /dev/null
+++ b/test/parallel/test-http-transfer-encoding-smuggling.js
@@ -0,0 +1,46 @@
+'use strict';
+
+const common = require('../common');
+
+const assert = require('assert');
+const http = require('http');
+const net = require('net');
+
+const msg = [
+ 'POST / HTTP/1.1',
+ 'Host: 127.0.0.1',
+ 'Transfer-Encoding: chunked',
+ 'Transfer-Encoding: chunked-false',
+ 'Connection: upgrade',
+ '',
+ '1',
+ 'A',
+ '0',
+ '',
+ 'GET /flag HTTP/1.1',
+ 'Host: 127.0.0.1',
+ '',
+ '',
+].join('\r\n');
+
+// Verify that the server is called only once even with a smuggled request.
+
+const server = http.createServer(common.mustCall((req, res) => {
+ res.end();
+}, 1));
+
+function send(next) {
+ const client = net.connect(server.address().port, 'localhost');
+ client.setEncoding('utf8');
+ client.on('error', common.mustNotCall());
+ client.on('end', next);
+ client.write(msg);
+ client.resume();
+}
+
+server.listen(0, common.mustCall((err) => {
+ assert.ifError(err);
+ send(common.mustCall(() => {
+ server.close();
+ }));
+}));

View File

@ -1,219 +0,0 @@
From 922ada77132c1b0b69c9a146822d762b2f9b912b Mon Sep 17 00:00:00 2001
From: Daniel Bevenius <daniel.bevenius@gmail.com>
Date: Fri, 22 Jan 2021 12:34:21 +0100
Subject: [PATCH] http2: add unknownProtocol timeout
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit add a configuration options named unknownProtocolTimeout
which can be specified to set a value for the timeout in milliseconds
that a server should wait when an unknowProtocol is sent to it. When
this happens a timer will be started and the if the socket has not been
destroyed during that time the timer callback will destoy it.
Refs: https://hackerone.com/reports/1043360
CVE-ID: CVE-2021-22883
PR-URL: https://github.com/nodejs/node/pull/246
Backport-PR-URL: https://github.com/nodejs/node/pull/250
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reference: https://github.com/nodejs/node/commit/922ada77132c1b0b69c9a146822d762b2f9b912b
---
doc/api/http2.md | 25 +++++++++++++-
lib/internal/http2/core.js | 31 ++++++++++++++---
.../test-http2-server-unknown-protocol.js | 33 +++++++++++++++++++
3 files changed, 84 insertions(+), 5 deletions(-)
create mode 100644 test/parallel/test-http2-server-unknown-protocol.js
diff --git a/doc/api/http2.md b/doc/api/http2.md
index 40a107f..d57a560 100644
--- a/doc/api/http2.md
+++ b/doc/api/http2.md
@@ -1908,7 +1908,9 @@ added: v8.4.0
The `'unknownProtocol'` event is emitted when a connecting client fails to
negotiate an allowed protocol (i.e. HTTP/2 or HTTP/1.1). The event handler
receives the socket for handling. If no listener is registered for this event,
-the connection is terminated. See the [Compatibility API][].
+the connection is terminated. A timeout may be specified using the
+`'unknownProtocolTimeout'` option passed to [`http2.createSecureServer()`][].
+See the [Compatibility API][].
#### `server.close([callback])`
<!-- YAML
@@ -1948,6 +1950,9 @@ error will be thrown.
<!-- YAML
added: v8.4.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs-private/node-private/pull/250
+ description: Added `unknownProtocolTimeout` option with a default of 10000.
- version:
- v12.18.0
pr-url: https://github.com/nodejs-private/node-private/pull/206
@@ -2050,6 +2055,10 @@ changes:
`Http2ServerResponse` class to use.
Useful for extending the original `Http2ServerResponse`.
**Default:** `Http2ServerResponse`.
+ * `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that
+ a server should wait when an [`'unknownProtocol'`][] is emitted. If the
+ socket has not been destroyed by that time the server will destroy it.
+ **Default:** `10000`.
* ...: Any [`net.createServer()`][] option can be provided.
* `onRequestHandler` {Function} See [Compatibility API][]
* Returns: {Http2Server}
@@ -2086,6 +2095,9 @@ server.listen(80);
<!-- YAML
added: v8.4.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs-private/node-private/pull/250
+ description: Added `unknownProtocolTimeout` option with a default of 10000.
- version:
- v12.18.0
pr-url: https://github.com/nodejs-private/node-private/pull/206
@@ -2178,6 +2190,10 @@ changes:
servers, the identity options (`pfx` or `key`/`cert`) are usually required.
* `origins` {string[]} An array of origin strings to send within an `ORIGIN`
frame immediately following creation of a new server `Http2Session`.
+ * `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that
+ a server should wait when an [`'unknownProtocol'`][] event is emitted. If
+ the socket has not been destroyed by that time the server will destroy it.
+ **Default:** `10000`.
* `onRequestHandler` {Function} See [Compatibility API][]
* Returns: {Http2SecureServer}
@@ -2211,6 +2227,9 @@ server.listen(80);
<!-- YAML
added: v8.4.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs-private/node-private/pull/250
+ description: Added `unknownProtocolTimeout` option with a default of 10000.
- version:
- v12.18.0
pr-url: https://github.com/nodejs-private/node-private/pull/206
@@ -2294,6 +2313,10 @@ changes:
instance passed to `connect` and the `options` object, and returns any
[`Duplex`][] stream that is to be used as the connection for this session.
* ...: Any [`net.connect()`][] or [`tls.connect()`][] options can be provided.
+ * `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that
+ a server should wait when an [`'unknownProtocol'`][] event is emitted. If
+ the socket has not been destroyed by that time the server will destroy it.
+ **Default:** `10000`.
* `listener` {Function} Will be registered as a one-time listener of the
[`'connect'`][] event.
* Returns: {ClientHttp2Session}
diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js
index 2116bc8..e9a63fe 100644
--- a/lib/internal/http2/core.js
+++ b/lib/internal/http2/core.js
@@ -33,7 +33,7 @@ const net = require('net');
const { Duplex } = require('stream');
const tls = require('tls');
const { URL } = require('url');
-const { setImmediate } = require('timers');
+const { setImmediate, setTimeout, clearTimeout } = require('timers');
const { kIncomingMessage } = require('_http_common');
const { kServerResponse } = require('_http_server');
@@ -2721,14 +2721,14 @@ function handleHeaderContinue(headers) {
this.emit('continue');
}
-const setTimeout = {
+const setTimeoutValue = {
configurable: true,
enumerable: true,
writable: true,
value: setStreamTimeout
};
-ObjectDefineProperty(Http2Stream.prototype, 'setTimeout', setTimeout);
-ObjectDefineProperty(Http2Session.prototype, 'setTimeout', setTimeout);
+ObjectDefineProperty(Http2Stream.prototype, 'setTimeout', setTimeoutValue);
+ObjectDefineProperty(Http2Session.prototype, 'setTimeout', setTimeoutValue);
// When the socket emits an error, destroy the associated Http2Session and
@@ -2788,6 +2788,22 @@ function connectionListener(socket) {
debug('Unknown protocol from %s:%s',
socket.remoteAddress, socket.remotePort);
if (!this.emit('unknownProtocol', socket)) {
+ debug('Unknown protocol timeout: %s', options.unknownProtocolTimeout);
+ // Install a timeout if the socket was not successfully closed, then
+ // destroy the socket to ensure that the underlying resources are
+ // released.
+ const timer = setTimeout(() => {
+ if (!socket.destroyed) {
+ debug('UnknownProtocol socket timeout, destroy socket');
+ socket.destroy();
+ }
+ }, options.unknownProtocolTimeout);
+ // Un-reference the timer to avoid blocking of application shutdown and
+ // clear the timeout if the socket was successfully closed.
+ timer.unref();
+
+ socket.once('close', () => clearTimeout(timer));
+
// We don't know what to do, so let's just tell the other side what's
// going on in a format that they *might* understand.
socket.end('HTTP/1.0 403 Forbidden\r\n' +
@@ -2836,6 +2852,13 @@ function initializeOptions(options) {
);
}
+ if (options.unknownProtocolTimeout !== undefined)
+ validateUint32(options.unknownProtocolTimeout, 'unknownProtocolTimeout');
+ else
+ // TODO(danbev): is this a good default value?
+ options.unknownProtocolTimeout = 10000;
+
+
// Used only with allowHTTP1
options.Http1IncomingMessage = options.Http1IncomingMessage ||
http.IncomingMessage;
diff --git a/test/parallel/test-http2-server-unknown-protocol.js b/test/parallel/test-http2-server-unknown-protocol.js
new file mode 100644
index 0000000..639bbe4
--- /dev/null
+++ b/test/parallel/test-http2-server-unknown-protocol.js
@@ -0,0 +1,33 @@
+'use strict';
+const common = require('../common');
+const fixtures = require('../common/fixtures');
+
+// This test verifies that when a server receives an unknownProtocol it will
+// not leave the socket open if the client does not close it.
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const h2 = require('http2');
+const tls = require('tls');
+
+const server = h2.createSecureServer({
+ key: fixtures.readKey('rsa_private.pem'),
+ cert: fixtures.readKey('rsa_cert.crt'),
+ unknownProtocolTimeout: 500,
+ allowHalfOpen: true
+});
+
+server.on('connection', (socket) => {
+ socket.on('close', common.mustCall(() => {
+ server.close();
+ }));
+});
+
+server.listen(0, function() {
+ tls.connect({
+ port: server.address().port,
+ rejectUnauthorized: false,
+ ALPNProtocols: ['bogus']
+ });
+});
--
2.23.0

View File

@ -1,38 +0,0 @@
From 1564752d553f582c8048ee45614f870ee2a446c9 Mon Sep 17 00:00:00 2001
From: Matteo Collina <hello@matteocollina.com>
Date: Thu, 14 Jan 2021 16:04:44 +0100
Subject: [PATCH] src: drop localhost6 as allowed host for inspector
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
CVE-ID: CVE-2021-22884
Refs: https://hackerone.com/bugs?report_id=1069487
PR-URL: https://github.com/nodejs/node/pull/244
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Mary Marchini <oss@mmarchini.me>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reference: https://github.com/nodejs/node/commit/1564752d553f582c8048ee45614f870ee2a446c9
---
src/inspector_socket.cc | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc
index a701928..3814565 100644
--- a/src/inspector_socket.cc
+++ b/src/inspector_socket.cc
@@ -584,8 +584,7 @@ class HttpHandler : public ProtocolHandler {
bool IsAllowedHost(const std::string& host_with_port) const {
std::string host = TrimPort(host_with_port);
return host.empty() || IsIPAddress(host)
- || node::StringEqualNoCase(host.data(), "localhost")
- || node::StringEqualNoCase(host.data(), "localhost6");
+ || node::StringEqualNoCase(host.data(), "localhost");
}
bool parsing_value_;
--
2.23.0

View File

@ -1,177 +0,0 @@
From d33aead28bcec32a2a450f884907a6d971631829 Mon Sep 17 00:00:00 2001
From: Ben Noordhuis <info@bnoordhuis.nl>
Date: Fri, 21 May 2021 11:23:36 +0200
Subject: [PATCH] deps: uv: cherry-pick 99c29c9c2c9b
Original commit message:
idna: fix OOB read in punycode decoder
Reported by Eric Sesterhenn in collaboration with
Cure53 and ExpressVPN.
Deleted unintroduced test files.
Reported-By: Eric Sesterhenn <eric.sesterhenn@x41-dsec.de>
PR-URL: https://github.com/libuv/libuv-private/pull/1
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
CVE-ID: CVE-2021-22918
Refs: https://hackerone.com/reports/1209681
PR-URL: https://github.com/nodejs-private/node-private/pull/267
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Beth Griggs <bgriggs@redhat.com>
---
deps/uv/src/idna.c | 49 ++++++++++++++++++++++++++++++++++------------
1 file changed, 36 insertions(+), 13 deletions(-)
diff --git a/deps/uv/src/idna.c b/deps/uv/src/idna.c
index 13ffac6..b44cb16 100644
--- a/deps/uv/src/idna.c
+++ b/deps/uv/src/idna.c
@@ -19,6 +19,7 @@
#include "uv.h"
#include "idna.h"
+#include <assert.h>
#include <string.h>
static unsigned uv__utf8_decode1_slow(const char** p,
@@ -32,7 +33,7 @@ static unsigned uv__utf8_decode1_slow(const char** p,
if (a > 0xF7)
return -1;
- switch (*p - pe) {
+ switch (pe - *p) {
default:
if (a > 0xEF) {
min = 0x10000;
@@ -62,6 +63,8 @@ static unsigned uv__utf8_decode1_slow(const char** p,
a = 0;
break;
}
+ /* Fall through. */
+ case 0:
return -1; /* Invalid continuation byte. */
}
@@ -88,6 +91,8 @@ static unsigned uv__utf8_decode1_slow(const char** p,
unsigned uv__utf8_decode1(const char** p, const char* pe) {
unsigned a;
+ assert(*p < pe);
+
a = (unsigned char) *(*p)++;
if (a < 128)
@@ -96,9 +101,6 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) {
return uv__utf8_decode1_slow(p, pe, a);
}
-#define foreach_codepoint(c, p, pe) \
- for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)
-
static int uv__idna_toascii_label(const char* s, const char* se,
char** d, char* de) {
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
@@ -121,15 +123,22 @@ static int uv__idna_toascii_label(const char* s, const char* se,
ss = s;
todo = 0;
- foreach_codepoint(c, &s, se) {
+ /* Note: after this loop we've visited all UTF-8 characters and know
+ * they're legal so we no longer need to check for decode errors.
+ */
+ while (s < se) {
+ c = uv__utf8_decode1(&s, se);
+
+ if (c == -1u)
+ return UV_EINVAL;
+
if (c < 128)
h++;
- else if (c == (unsigned) -1)
- return UV_EINVAL;
else
todo++;
}
+ /* Only write "xn--" when there are non-ASCII characters. */
if (todo > 0) {
if (*d < de) *(*d)++ = 'x';
if (*d < de) *(*d)++ = 'n';
@@ -137,9 +146,13 @@ static int uv__idna_toascii_label(const char* s, const char* se,
if (*d < de) *(*d)++ = '-';
}
+ /* Write ASCII characters. */
x = 0;
s = ss;
- foreach_codepoint(c, &s, se) {
+ while (s < se) {
+ c = uv__utf8_decode1(&s, se);
+ assert(c != -1u);
+
if (c > 127)
continue;
@@ -166,10 +179,15 @@ static int uv__idna_toascii_label(const char* s, const char* se,
while (todo > 0) {
m = -1;
s = ss;
- foreach_codepoint(c, &s, se)
+
+ while (s < se) {
+ c = uv__utf8_decode1(&s, se);
+ assert(c != -1u);
+
if (c >= n)
if (c < m)
m = c;
+ }
x = m - n;
y = h + 1;
@@ -181,7 +199,10 @@ static int uv__idna_toascii_label(const char* s, const char* se,
n = m;
s = ss;
- foreach_codepoint(c, &s, se) {
+ while (s < se) {
+ c = uv__utf8_decode1(&s, se);
+ assert(c != -1u);
+
if (c < n)
if (++delta == 0)
return UV_E2BIG; /* Overflow. */
@@ -245,8 +266,6 @@ static int uv__idna_toascii_label(const char* s, const char* se,
return 0;
}
-#undef foreach_codepoint
-
long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
const char* si;
const char* st;
@@ -256,10 +275,14 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
ds = d;
- for (si = s; si < se; /* empty */) {
+ si = s;
+ while (si < se) {
st = si;
c = uv__utf8_decode1(&si, se);
+ if (c == -1u)
+ return UV_EINVAL;
+
if (c != '.')
if (c != 0x3002) /* 。 */
if (c != 0xFF0E) /* */
--
2.27.0

View File

@ -1,71 +0,0 @@
From b263f2585ab53f56e0e22b46cf1f8519a8af8a05 Mon Sep 17 00:00:00 2001
From: Akshay K <iit.akshay@gmail.com>
Date: Mon, 26 Jul 2021 08:21:51 -0400
Subject: [PATCH] http2: on receiving rst_stream with cancel code add it to
pending list
PR-URL: https://github.com/nodejs/node/pull/39423
Backport-PR-URL: https://github.com/nodejs/node/pull/39527
Fixes: https://github.com/nodejs/node/issues/38964
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
---
src/node_http2.cc | 17 +++++++++++++++++
src/node_http2.h | 16 ++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/src/node_http2.cc b/src/node_http2.cc
index dec6d7dab9ee..cc21373521e4 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -2135,6 +2135,23 @@ 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 (session_->is_in_scope() && 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
diff --git a/src/node_http2.h b/src/node_http2.h
index 045bdfd716da..a59de18f920a 100644
--- a/src/node_http2.h
+++ b/src/node_http2.h
@@ -764,6 +764,22 @@ class Http2Session : public AsyncWrap,
return (flags_ & SESSION_STATE_CLOSED) || session_ == nullptr;
}
+
+ // The changes are backported and exposes APIs to check the
+ // status flag of `Http2Session`
+#define IS_FLAG(name, flag) \
+ bool is_##name() const { return flags_ & flag; }
+
+ IS_FLAG(in_scope, SESSION_STATE_HAS_SCOPE)
+ IS_FLAG(write_scheduled, SESSION_STATE_WRITE_SCHEDULED)
+ IS_FLAG(closing, SESSION_STATE_CLOSING)
+ IS_FLAG(sending, SESSION_STATE_SENDING)
+ IS_FLAG(write_in_progress, SESSION_STATE_WRITE_IN_PROGRESS)
+ IS_FLAG(reading_stopped, SESSION_STATE_READING_STOPPED)
+ IS_FLAG(receive_paused, SESSION_STATE_NGHTTP2_RECV_PAUSED)
+
+#undef IS_FLAG
+
// Schedule a write if nghttp2 indicates it wants to write to the socket.
void MaybeScheduleWrite();

View File

@ -1,46 +0,0 @@
From 1b61414ccdd0e1b5969219ba3ec7664d1f3ab495 Mon Sep 17 00:00:00 2001
From: Akshay K <iit.akshay@gmail.com>
Date: Fri, 30 Jul 2021 18:46:45 -0400
Subject: [PATCH] http2: update handling of rst_stream with error code
NGHTTP2_CANCEL
---
src/node_http2.cc | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/node_http2.cc b/src/node_http2.cc
index edbf531..6027318 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -2136,18 +2136,19 @@ 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
+ auto is_stream_cancel = [](const uint32_t code) {
+ return code == NGHTTP2_CANCEL;
+ };
+
+ // If RST_STREAM frame is received with error code NGHTTP2_CANCEL,
+ // add it to the pending list and don't force purge the data. It is
+ // to avoids the double free error due to unwanted behavior of nghttp2.
+
+ // Add stream to the pending list only 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 (session_->is_in_scope() && IsReading()) {
+ if (session_->is_in_scope() && is_stream_cancel(code)) {
session_->AddPendingRstStream(id_);
return;
}
--
2.27.0

View File

@ -1,53 +0,0 @@
From 9b39a6b0c5e41a67c0fd180c884dca1b38e16b7b Mon Sep 17 00:00:00 2001
From: Akshay K <iit.akshay@gmail.com>
Date: Thu, 5 Aug 2021 03:01:43 -0400
Subject: [PATCH] http2: add tests for cancel event while client is paused
reading
---
.../test-http2-cancel-while-client-reading.js | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 test/parallel/test-http2-cancel-while-client-reading.js
diff --git a/test/parallel/test-http2-cancel-while-client-reading.js b/test/parallel/test-http2-cancel-while-client-reading.js
new file mode 100644
index 000000000000..0605a02e1166
--- /dev/null
+++ b/test/parallel/test-http2-cancel-while-client-reading.js
@@ -0,0 +1,36 @@
+'use strict';
+const common = require('../common');
+const fixtures = require('../common/fixtures');
+if (!common.hasCrypto) {
+ common.skip('missing crypto');
+}
+
+const http2 = require('http2');
+const key = fixtures.readKey('agent1-key.pem', 'binary');
+const cert = fixtures.readKey('agent1-cert.pem', 'binary');
+
+const server = http2.createSecureServer({ key, cert });
+
+let client_stream;
+
+server.on('stream', common.mustCall(function(stream) {
+ stream.resume();
+ stream.on('data', function(chunk) {
+ stream.write(chunk);
+ client_stream.pause();
+ client_stream.close(http2.constants.NGHTTP2_CANCEL);
+ });
+}));
+
+server.listen(0, function() {
+ const client = http2.connect(`https://localhost:${server.address().port}`,
+ { rejectUnauthorized: false }
+ );
+ client_stream = client.request({ ':method': 'POST' });
+ client_stream.on('close', common.mustCall(() => {
+ client.close();
+ server.close();
+ }));
+ client_stream.resume();
+ client_stream.write(Buffer.alloc(1024 * 1024));
+});

View File

@ -1,10 +1,10 @@
%bcond_with bootstrap %bcond_with bootstrap
%global baserelease 7 %global baserelease 1
%{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}} %{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}}
%global nodejs_epoch 1 %global nodejs_epoch 1
%global nodejs_major 12 %global nodejs_major 12
%global nodejs_minor 18 %global nodejs_minor 22
%global nodejs_patch 4 %global nodejs_patch 11
%global nodejs_abi %{nodejs_major}.%{nodejs_minor} %global nodejs_abi %{nodejs_major}.%{nodejs_minor}
%global nodejs_soversion 72 %global nodejs_soversion 72
%global nodejs_version %{nodejs_major}.%{nodejs_minor}.%{nodejs_patch} %global nodejs_version %{nodejs_major}.%{nodejs_minor}.%{nodejs_patch}
@ -19,19 +19,19 @@
%global v8_version %{v8_major}.%{v8_minor}.%{v8_build}.%{v8_patch} %global v8_version %{v8_major}.%{v8_minor}.%{v8_build}.%{v8_patch}
%global v8_release %{nodejs_epoch}.%{nodejs_major}.%{nodejs_minor}.%{nodejs_patch}.%{nodejs_release} %global v8_release %{nodejs_epoch}.%{nodejs_major}.%{nodejs_minor}.%{nodejs_patch}.%{nodejs_release}
%global c_ares_major 1 %global c_ares_major 1
%global c_ares_minor 16 %global c_ares_minor 18
%global c_ares_patch 0 %global c_ares_patch 1
%global c_ares_version %{c_ares_major}.%{c_ares_minor}.%{c_ares_patch} %global c_ares_version %{c_ares_major}.%{c_ares_minor}.%{c_ares_patch}
%global http_parser_major 2 %global http_parser_major 2
%global http_parser_minor 9 %global http_parser_minor 9
%global http_parser_patch 3 %global http_parser_patch 4
%global http_parser_version %{http_parser_major}.%{http_parser_minor}.%{http_parser_patch} %global http_parser_version %{http_parser_major}.%{http_parser_minor}.%{http_parser_patch}
%global llhttp_major 2 %global llhttp_major 2
%global llhttp_minor 1 %global llhttp_minor 1
%global llhttp_patch 2 %global llhttp_patch 4
%global llhttp_version %{llhttp_major}.%{llhttp_minor}.%{llhttp_patch} %global llhttp_version %{llhttp_major}.%{llhttp_minor}.%{llhttp_patch}
%global libuv_major 1 %global libuv_major 1
%global libuv_minor 38 %global libuv_minor 40
%global libuv_patch 0 %global libuv_patch 0
%global libuv_version %{libuv_major}.%{libuv_minor}.%{libuv_patch} %global libuv_version %{libuv_major}.%{libuv_minor}.%{libuv_patch}
%global nghttp2_major 1 %global nghttp2_major 1
@ -52,11 +52,11 @@
%global npm_epoch 1 %global npm_epoch 1
%global npm_major 6 %global npm_major 6
%global npm_minor 14 %global npm_minor 14
%global npm_patch 6 %global npm_patch 16
%global npm_version %{npm_major}.%{npm_minor}.%{npm_patch} %global npm_version %{npm_major}.%{npm_minor}.%{npm_patch}
%global uvwasi_major 0 %global uvwasi_major 0
%global uvwasi_minor 0 %global uvwasi_minor 0
%global uvwasi_patch 9 %global uvwasi_patch 11
%global uvwasi_version %{uvwasi_major}.%{uvwasi_minor}.%{uvwasi_patch} %global uvwasi_version %{uvwasi_major}.%{uvwasi_minor}.%{uvwasi_patch}
%global histogram_major 0 %global histogram_major 0
%global histogram_minor 9 %global histogram_minor 9
@ -81,20 +81,8 @@ Source7: nodejs_native.attr
Patch0001: 0001-Disable-running-gyp-on-shared-deps.patch Patch0001: 0001-Disable-running-gyp-on-shared-deps.patch
Patch0002: 0002-Install-both-binaries-and-use-libdir.patch Patch0002: 0002-Install-both-binaries-and-use-libdir.patch
%ifarch aarch64 Patch0003: 0004-Make-AARCH64-compile-on-64KB-physical-pages.patch
Patch0003: 0003-Modify-openEuler-aarch64-v8_os_page_size-to-64.patch Patch00010: 0005-use-getauxval-in-node_main_cc.patch
%endif
Patch0004: 0004-Make-AARCH64-compile-on-64KB-physical-pages.patch
Patch0005: CVE-2020-8265.patch
Patch0006: CVE-2020-8287-1.patch
Patch0007: CVE-2020-8287-2.patch
Patch0008: CVE-2021-22883.patch
Patch0009: CVE-2021-22884.patch
Patch00010: CVE-2021-22918.patch
Patch00011: 0005-use-getauxval-in-node_main_cc.patch
Patch00012: CVE-2021-22930-1.patch
Patch00013: CVE-2021-22930-2.patch
Patch00014: CVE-2021-22930-3.patch
BuildRequires: python3-devel BuildRequires: python3-devel
BuildRequires: zlib-devel BuildRequires: zlib-devel
@ -196,7 +184,7 @@ package to save space if non-English locales are not needed.
Summary: v8 - development headers Summary: v8 - development headers
Epoch: %{v8_epoch} Epoch: %{v8_epoch}
Version: %{v8_version} Version: %{v8_version}
Release: %{v8_release}%{?dist} Release: %{v8_release}
Requires: %{name}-devel%{?_isa} = %{nodejs_epoch}:%{nodejs_version}-%{nodejs_release}%{?dist} Requires: %{name}-devel%{?_isa} = %{nodejs_epoch}:%{nodejs_version}-%{nodejs_release}%{?dist}
%description -n v8-devel %description -n v8-devel
@ -206,7 +194,7 @@ Development headers for the v8 runtime.
Summary: Node.js Package Manager Summary: Node.js Package Manager
Epoch: %{npm_epoch} Epoch: %{npm_epoch}
Version: %{npm_version} Version: %{npm_version}
Release: %{npm_release}%{?dist} Release: %{npm_release}
Obsoletes: npm < 0:3.5.4-6 Obsoletes: npm < 0:3.5.4-6
Provides: npm = %{npm_epoch}:%{npm_version} Provides: npm = %{npm_epoch}:%{npm_version}
@ -497,6 +485,9 @@ end
%{_pkgdocdir}/npm/docs %{_pkgdocdir}/npm/docs
%changelog %changelog
* Mon Mar 28 2022 wangkai <wangkai385@huawei.com> 1:12.22.11-1
- Update to 12.22.11, fix some cves.
* Thu Oct 21 2021 yaoxin <yaoxin30@huawei.com> - 1:12.18.4-7 * Thu Oct 21 2021 yaoxin <yaoxin30@huawei.com> - 1:12.18.4-7
- fix CVE-2021-22930 - fix CVE-2021-22930