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

Crash in Node v8.x at lib/_tls_legacy.js.onclienthello() #26428

Closed
alexfernandez opened this issue Mar 4, 2019 · 5 comments
Closed

Crash in Node v8.x at lib/_tls_legacy.js.onclienthello() #26428

alexfernandez opened this issue Mar 4, 2019 · 5 comments
Labels
tls Issues and PRs related to the tls subsystem.

Comments

@alexfernandez
Copy link

alexfernandez commented Mar 4, 2019

  • Version: 8.15.0
  • Platform: Ubuntu server.
  • Subsystem: TLS

At my company we have a TCP server accepting connections and securing them with tls.createSecurePair(). When there is high load in the server, usually due to lots of I/O traffic, we start seeing exceptions generated by the Node.js runtime.

The crash is located at lib/_tls_legacy.js/onclienthello(): when the TLS connection is destroyed before the setImmediate() can run, this situation results in a TypeError: Cannot read property 'loadSession' of null.

The attached code destroy-early.js shows this issue with sample certificates from freelan:

$ node destroy-early.js
(node:3072) [DEP0064] DeprecationWarning: tls.createSecurePair() is deprecated. Please use tls.Socket instead.
Encrypted bytes 220
_tls_legacy.js:660
      self.ssl.loadSession(session);
               ^

TypeError: Cannot read property 'loadSession' of null
    at Immediate._onImmediate (_tls_legacy.js:660:16)
    at runCallback (timers.js:789:20)
    at tryOnImmediate (timers.js:751:5)
    at processImmediate [as _immediateCallback] (timers.js:722:5)

Essentially we open a couple of secure pairs, client and server, send cleartext to the client and then destroy the socket inside a setImmediate():

setImmediate(() => serverPair.destroy());

However if the socket is destroyed right away it works:

serverPair.destroy();

Bug exists in 8.x since at least 8.9.4 up until the latest 8.15.0. It is not present in v10 since _tls_legacy.js has disappeared.

We are open to sending a pull request ourselves, essentially a one liner ensuring that self.ssl is not null before proceeding in onclienthello().

Thanks!
destroy-early.tar.gz

@bnoordhuis bnoordhuis added tls Issues and PRs related to the tls subsystem. v8.x labels Mar 5, 2019
@bnoordhuis
Copy link
Member

Thanks for the bug report. After checking the code I think there may be more than one bug to fix in lib/_tls_legacy.js. Session resumption with tls.createSecurePair() seems pretty broken at the moment. I'll have a look.

@alexfernandez
Copy link
Author

Thanks! We were thinking of a simple fix since that file disappears in v10.x, but any deeper solutions are of course welcome.

bnoordhuis added a commit to bnoordhuis/io.js that referenced this issue Mar 5, 2019
This seems to have been broken ever since its introduction 5 years ago
in commit 75ea11f ("tls: introduce asynchronous `newSession`") and
no one complained but that's not going to stop me from fixing it anyway
because otherwise I can't write a regression test for issue nodejs#26428.

Refs: nodejs#26428
bnoordhuis added a commit to bnoordhuis/io.js that referenced this issue Mar 5, 2019
There is a time window between the first and the last step of processing
the clienthello event and the SecurePair may have been destroyed during
that interval.

Fixes: nodejs#26428
@bnoordhuis
Copy link
Member

#26452 - if you have an opportunity to test it out, that would be great.

@alexfernandez
Copy link
Author

alexfernandez commented Mar 5, 2019

Tested #26452 with our test case destroy-early.js, works beautifully! Thanks 👍

 $ node --version
v8.9.4
 $ node destroy-early.js 
(node:17638) [DEP0064] DeprecationWarning: tls.createSecurePair() is deprecated. Please use tls.Socket instead.
Encrypted bytes 220
_tls_legacy.js:660
      self.ssl.loadSession(session);
               ^

TypeError: Cannot read property 'loadSession' of null
    at Immediate._onImmediate (_tls_legacy.js:660:16)
    at runCallback (timers.js:789:20)
    at tryOnImmediate (timers.js:751:5)
    at processImmediate [as _immediateCallback] (timers.js:722:5)

 $ ../../node/node --version
v8.15.2-pre
 $ ../../node/node destroy-early.js 
(node:17652) [DEP0064] DeprecationWarning: tls.createSecurePair() is deprecated. Please use tls.TLSSocket instead.
Encrypted bytes 220
Client error: Error: socket hang up

Note: the socket hang up error is the expected outcome once the the TypeError is solved.

BethGriggs pushed a commit that referenced this issue Mar 21, 2019
This seems to have been broken ever since its introduction 5 years ago
in commit 75ea11f ("tls: introduce asynchronous `newSession`") and
no one complained but that's not going to stop me from fixing it anyway
because otherwise I can't write a regression test for issue #26428.

Refs: #26428

PR-URL: #26452
Fixes: #26428
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Beth Griggs <Bethany.Griggs@uk.ibm.com>
BethGriggs pushed a commit that referenced this issue Mar 21, 2019
There is a time window between the first and the last step of processing
the clienthello event and the SecurePair may have been destroyed during
that interval.

Fixes: #26428

PR-URL: #26452
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Beth Griggs <Bethany.Griggs@uk.ibm.com>
@bnoordhuis
Copy link
Member

#26452 was merged in March but apparently didn't auto-close this issue. I'll do it the old-fashioned way then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tls Issues and PRs related to the tls subsystem.
Projects
None yet
Development

No branches or pull requests

2 participants