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

race condition bug in minio http server #5291

Closed
aead opened this issue Dec 14, 2017 · 9 comments · Fixed by #5245
Closed

race condition bug in minio http server #5291

aead opened this issue Dec 14, 2017 · 9 comments · Fixed by #5245

Comments

@aead
Copy link
Member

aead commented Dec 14, 2017

The minio http server contains a race condition bug caused by a shared pointer of tls.Config.
Take a look at the following line. The comment says: "Take a copy" but we don't copy - we share the pointer. This can lead to race conditions when the tls.Config is accessed from the code which spans the server and the server itself.

Expected Behavior

The tls.Config should be copied (cloned)

Current Behavior

The tls.Config is shared

Possible Solution

Replace https://github.com/minio/minio/blob/master/pkg/http/server.go#L67 with
lsConfig := srv.TLSConfig.Clone()

Steps to Reproduce (for bugs)

Run the following test with the race detector go test -race -v:

func TestTLSCiphers(t *testing.T) {
	certificate, err := getTLSCert()
	if err != nil {
		t.Fatalf("Unable to parse private/certificate data. %v\n", err)
	}
	port := getNextPort()
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, world")
	})
	server := NewServer([]string{"127.0.0.1:" + port}, handler, &certificate)
	go func() { panic(server.Start()) }()
	defer server.Shutdown()
	for i, test := range tlsCipherSuitesTests {
		client := http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{
					InsecureSkipVerify: true,
					CipherSuites:       test.ciphers,
				},
			},
		}
		_, err := client.Get("https://127.0.0.1:" + port + "/")
		if err != nil && !test.shouldFail {
			t.Fatalf("Test %d: Failed to execute GET request: %s", i, err)
		}
		if err == nil && test.shouldFail {
			t.Fatalf("Test %d: Successfully connected to server but expected connection failure", i)
		}
	}
}

Context

Detected while fixing #5245

Your Environment

master

@aead aead self-assigned this Dec 14, 2017
aead pushed a commit to aead/minio that referenced this issue Dec 14, 2017
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes minio#5244
Fixes minio#5291
@fwessels
Copy link
Contributor

Nice catch -- are there any other places in the code where the same mistake could be made?

aead pushed a commit to aead/minio that referenced this issue Dec 15, 2017
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes minio#5244
Fixes minio#5291
aead pushed a commit to aead/minio that referenced this issue Dec 15, 2017
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes minio#5244
Fixes minio#5291
@aead
Copy link
Member Author

aead commented Dec 15, 2017

Probably... For example 4 lines further down: https://github.com/minio/minio/blob/master/pkg/http/server.go#L72 - We don't copy the slice... However it's very unlikely that somebody changes the addresses - nevertheless we should fix it, too.

@balamurugana
Copy link
Member

The idea of taking copy of server fields is to safely start the server irrespective of field value changes. As addrs argument is to NewServer(), we would need to safely store. Basically Addrs should be a set.StringSet and NewServer() could create the set from the inputted addrs

@aead
Copy link
Member Author

aead commented Dec 15, 2017

The idea of taking copy of server fields is to safely start the server irrespective of field value changes.

Correct. The straight-farword solution (IMO) to this would be:

addrs := make([]string, len(srv.Addrs))
copy(addrs, srv.Addrs)

@fwessels
Copy link
Contributor

Yes, please fix

aead pushed a commit to aead/minio that referenced this issue Dec 15, 2017
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes minio#5244
Fixes minio#5291
@aead aead added this to the Next Release milestone Dec 15, 2017
@balamurugana
Copy link
Member

Correct. The straight-farword solution (IMO) to this would be:

addrs := make([]string, len(srv.Addrs))
copy(addrs, srv.Addrs)

I won't prefer this patching. As I mentioned above, we should fix properly by using set.StringSet which fixes completely i.e. no more duplicate addr where we error out later.

@aead
Copy link
Member Author

aead commented Dec 16, 2017

While I agree that we should fix duplicate addresses I still would not do this in Start.
It looks odd from an API point of view if I can create a server with duplicate addresses but cannot start it:

server := NewServer(addresses, ...)
server.Start() // fails because of duplicate addresses

or do you want to just ignore duplicates and not error out?

aead pushed a commit to aead/minio that referenced this issue Dec 16, 2017
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes minio#5244
Fixes minio#5291
@balamurugana
Copy link
Member

While I agree that we should fix duplicate addresses I still would not do this in Start. It looks odd from an API point of view if I can create a server with duplicate addresses but cannot start it:

You are right. The exact way of fixing this problem is like below

  1. Change Addrs field type to set.StringSet from []string currently.
  2. In NewServer(), assign addrs arg to Addrs by set.CreateStringSet(addrs...)
  3. In Start(), have addrs = srv.Addrs.ToSlice()

Here, duplicate addrs are ignored i.e. no error is thrown. As Addrs is a set.StringSet there is no way user adds/modifies Addrs with duplicates.

aead pushed a commit to aead/minio that referenced this issue Jan 10, 2018
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes minio#5244
Fixes minio#5291
nitisht pushed a commit that referenced this issue Jan 13, 2018
This change restircts the supported cipher suites of the minio server.
The server only supports AEAD ciphers (Chacha20Poly1305 and 
AES-GCM)

The supported cipher suites are:
 - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
 - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

Fixes #5244 and #5291
@nitisht nitisht added the fixed label Jan 13, 2018
@lock
Copy link

lock bot commented Apr 26, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Apr 26, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants