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

fix deadlock in crypto setup when it is closed while handling a message #2802

Merged
merged 1 commit into from
Sep 26, 2020

Conversation

marten-seemann
Copy link
Member

Fixes #2737.

@egonelbre's analysis (option B) in #2737 (comment) was right.

Unfortunately, I didn't manage to write an integration test that would trigger the bug, so I'm not 100% sure that this fix actually works under all circumstances.

@codecov
Copy link

codecov bot commented Sep 25, 2020

Codecov Report

Merging #2802 into master will decrease coverage by 0.04%.
The diff coverage is 61.54%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2802      +/-   ##
==========================================
- Coverage   86.02%   85.98%   -0.04%     
==========================================
  Files         133      133              
  Lines       12063    12068       +5     
==========================================
  Hits        10376    10376              
- Misses       1355     1360       +5     
  Partials      332      332              
Impacted Files Coverage Δ
internal/handshake/crypto_setup.go 65.46% <61.54%> (-0.66%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 93e733a...9ce5426. Read the comment docs.

@egonelbre
Copy link
Contributor

I often try to separate the concurrency bits and channel handling into a separate struct, such that it can be separately tested... however seems bit difficult here.

If you could hook into h.conn.Handshake somehow, then you could call SendAlert from it. And concurrently call Close.

@@ -506,11 +507,12 @@ func (h *cryptoSetup) ReadHandshakeMessage() ([]byte, error) {
} else {
Copy link
Contributor

@egonelbre egonelbre Sep 25, 2020

Choose a reason for hiding this comment

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

On line 488, is there a possibility the go func() { <-h.isReadingHandshakeMessage gets stuck somehow?

I noticed that it doesn't have an obvious (to me) condition for shutting down on close.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. That one should probably be protected by a select statement as well.

@marten-seemann
Copy link
Member Author

@egonelbre Yes, that would be nice, but the way the TLS library is structured doesn't allow that.
Ideally, the library would expose a HandleHandshakeMessage() (response []byte, err error) method. Instead, we need to call Handshake, which basically does the following:

func Handshake() {
    for {
          msg := cryptosetup.ReadHandshakeMessage()
          if err := handleMsg(msg); err != nil {
               cryptosetup.SendAlert()
               break
          }
          if handshake complete {
               break
          }
    }
}

@marten-seemann marten-seemann force-pushed the fix-crypto-setup-deadlock branch from a44c65d to 9ce5426 Compare September 25, 2020 07:06
@marten-seemann marten-seemann merged commit e915472 into master Sep 26, 2020
@marten-seemann marten-seemann deleted the fix-crypto-setup-deadlock branch September 26, 2020 10:56
@aschmahmann aschmahmann mentioned this pull request Feb 18, 2021
73 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Long security handshake/leaked goroutine
3 participants