Skip to content

Do not use tlsconfig.Clone, which is unsafe in go 1.7 if the config is already being used#2013

Merged
aaronlehmann merged 2 commits into
moby:masterfrom
cyli:fix-update-ca-data-race
Mar 7, 2017
Merged

Do not use tlsconfig.Clone, which is unsafe in go 1.7 if the config is already being used#2013
aaronlehmann merged 2 commits into
moby:masterfrom
cyli:fix-update-ca-data-race

Conversation

@cyli
Copy link
Copy Markdown
Contributor

@cyli cyli commented Mar 7, 2017

Rather than clone the config, since we already have utilities to create a new TLS configuration for the client and server using the TLS certs themselves and the root pool, just recreate a new TLS configuration rather than attempt to clone the existing one.

Accessing the certificates in the tls.Config object does not cause a data race:

package main_test

import (
	"crypto/tls"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"
)

// TestDockerTLSConfigClone attempts to trigger a data race when calling config.Clone while a server is running
func TestDockerTLSConfigClone(t *testing.T) {
	client := http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	s := httptest.NewTLSServer(http.DefaultServeMux)
	defer s.Close()
	go func() {
		fmt.Println(s.TLS.Certificates)
	}()

	done := make(chan struct{})
	go func() {
		defer close(done)
		_, err := client.Get(s.URL)
		require.NoError(t, err)
	}()

	<-done
}

is fine under go 1.7 and go 1.8

Fixes #2012.

Comment thread ca/config.go Outdated
}

clientTLSConfig, err := NewClientTLSConfig(tlsKeyPair, rootCA.Pool, CARole)
clientTLSConfig, err := NewClientTLSConfig([]tls.Certificate{*tlsKeyPair}, rootCA.Pool, ManagerRole)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Both are fine, since the manager certificate has both as DNS names, but for consistency I changed this to the manager role instead.

Comment thread ca/config.go Outdated
if s.ClientTLSCreds != nil {
s.ClientTLSCreds.UpdateCAs(rootCA.Pool, nil)
clientConfig := s.ClientTLSCreds.Config()
updatedClientConfig, err := NewClientTLSConfig(clientConfig.Certificates, rootCA.Pool, ManagerRole)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wouldn't this reintroduce this issue: #1983 (comment) ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah right... :| in that case I will go with your suggestion of keeping a copy of the TLS config. I was hoping to do most of the cloning in the config. I actually wonder if we need to take out a lock on SecurityConfig, though, as well because RenewTLSConfigNow might update everything with an old root CA after UpdateRootCA is called.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added a test which attempted to simultaneously update the certs and update the root CA. It looks like I do need a lock on the root CA, because otherwise renewing the cert would overwrite the root CA changes. :|

@codecov-io
Copy link
Copy Markdown

codecov-io commented Mar 7, 2017

Codecov Report

Merging #2013 into master will decrease coverage by -0.17%.
The diff coverage is 72.41%.

@@            Coverage Diff             @@
##           master    #2013      +/-   ##
==========================================
- Coverage   53.96%   53.79%   -0.17%     
==========================================
  Files         109      109              
  Lines       18997    18980      -17     
==========================================
- Hits        10251    10211      -40     
- Misses       7527     7532       +5     
- Partials     1219     1237      +18

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 dd916da...5636661. Read the comment docs.

…ig is already

being used in a server.

Signed-off-by: cyli <ying.li@docker.com>
@cyli cyli force-pushed the fix-update-ca-data-race branch from a49ce81 to 57ce2d4 Compare March 7, 2017 18:58
Signed-off-by: cyli <ying.li@docker.com>
@cyli
Copy link
Copy Markdown
Contributor Author

cyli commented Mar 7, 2017

cc @diogomonica

@aaronlehmann
Copy link
Copy Markdown
Collaborator

LGTM

@aaronlehmann
Copy link
Copy Markdown
Collaborator

Merging to fix CI problems. @diogomonica: feel free to review post-merge.

@aaronlehmann aaronlehmann merged commit d60ccf3 into moby:master Mar 7, 2017
@cyli cyli deleted the fix-update-ca-data-race branch March 7, 2017 23:20
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.

Data race in UpdateCAs

3 participants