Jelajahi Sumber

opts: ParseTCPAddr(): fix validation of hosts to not ignore path elements

There was a discrepancy between what `ParseTCPAddr()` accepted, and what the
daemon was able to use, resulting in the daemon to start, but fail to create
listeners for the specified host.

Before this patch:

    dockerd -H tcp://127.0.0.1:2375/
    INFO[2022-04-03T10:18:06.417502600Z] Starting up
    ...
    failed to load listeners: listen tcp: address tcp/2375/: unknown port

    dockerd -H 127.0.0.1:2375/path
    INFO[2022-04-03T10:18:06.417502600Z] Starting up
    ...
    failed to load listeners: listen tcp: address tcp/5555/path: unknown port

After this patch:

    dockerd -H tcp://127.0.0.1:2375/
    Status: invalid argument "tcp://127.0.0.1:2375/" for "-H, --host" flag: invalid bind address (127.0.0.1:2375/): should not contain a path element
    See 'dockerd --help'., Code: 125

    dockerd -H 127.0.0.1:2375/path
    Status: invalid argument "127.0.0.1:2375/path" for "-H, --host" flag: invalid bind address (127.0.0.1:2375/path): should not contain a path element
    See 'dockerd --help'., Code: 125

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 3 tahun lalu
induk
melakukan
ecbfe73193
2 mengubah file dengan 55 tambahan dan 43 penghapusan
  1. 6 1
      opts/hosts.go
  2. 49 42
      opts/hosts_test.go

+ 6 - 1
opts/hosts.go

@@ -9,6 +9,7 @@ import (
 	"strings"
 
 	"github.com/docker/docker/pkg/homedir"
+	"github.com/pkg/errors"
 )
 
 const (
@@ -162,7 +163,11 @@ func ParseTCPAddr(tryAddr string, defaultAddr string) (string, error) {
 		return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
 	}
 
-	return fmt.Sprintf("tcp://%s%s", net.JoinHostPort(host, port), u.Path), nil
+	if u.Path != "" {
+		return "", errors.Errorf("invalid bind address (%s): should not contain a path element", tryAddr)
+	}
+
+	return "tcp://" + net.JoinHostPort(host, port), nil
 }
 
 // ValidateExtraHost validates that the specified string is a valid extrahost and returns it.

+ 49 - 42
opts/hosts_test.go

@@ -13,6 +13,14 @@ func TestParseHost(t *testing.T) {
 		"unknown://",
 		"tcp://:port",
 		"tcp://invalid:port",
+		"tcp://:5555/",
+		"tcp://:5555/p",
+		"tcp://0.0.0.0:5555/",
+		"tcp://0.0.0.0:5555/p",
+		"tcp://[::1]:/",
+		"tcp://[::1]:5555/",
+		"tcp://[::1]:5555/p",
+		" tcp://:5555/path ",
 	}
 
 	valid := map[string]string{
@@ -29,7 +37,6 @@ func TestParseHost(t *testing.T) {
 		"tcp://192.168.0.0:12000":  "tcp://192.168.0.0:12000",
 		"tcp://192.168:8080":       "tcp://192.168:8080",
 		"tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P
-		" tcp://:7777/path ":       fmt.Sprintf("tcp://%s:7777/path", DefaultHTTPHost),
 		"tcp://docker.com:2375":    "tcp://docker.com:2375",
 		"unix://":                  "unix://" + DefaultUnixSocket,
 		"unix://path/to/socket":    "unix://path/to/socket",
@@ -60,27 +67,27 @@ func TestParseDockerDaemonHost(t *testing.T) {
 		"tcp://unix:///run/docker.sock": "Invalid proto, expected tcp: unix:///run/docker.sock",
 		" tcp://:7777/path ":            "Invalid bind address format:  tcp://:7777/path ",
 		"":                              "Invalid bind address format: ",
+		":5555/path":                    "invalid bind address (:5555/path): should not contain a path element",
+		"0.0.0.1:5555/path":             "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
+		"[::1]:5555/path":               "invalid bind address ([::1]:5555/path): should not contain a path element",
+		"[0:0:0:0:0:0:0:1]:5555/path":   "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
+		"tcp://:5555/path":              "invalid bind address (:5555/path): should not contain a path element",
+		"localhost:5555/path":           "invalid bind address (localhost:5555/path): should not contain a path element",
 	}
 	valids := map[string]string{
-		"0.0.0.1:":                    "tcp://0.0.0.1:2375",
-		"0.0.0.1:5555":                "tcp://0.0.0.1:5555",
-		"0.0.0.1:5555/path":           "tcp://0.0.0.1:5555/path",
-		"[::1]:":                      "tcp://[::1]:2375",
-		"[::1]:5555/path":             "tcp://[::1]:5555/path",
-		"[0:0:0:0:0:0:0:1]:":          "tcp://[0:0:0:0:0:0:0:1]:2375",
-		"[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
-		":6666":                       fmt.Sprintf("tcp://%s:6666", DefaultHTTPHost),
-		":6666/path":                  fmt.Sprintf("tcp://%s:6666/path", DefaultHTTPHost),
-		"tcp://":                      DefaultTCPHost,
-		"tcp://:7777":                 fmt.Sprintf("tcp://%s:7777", DefaultHTTPHost),
-		"tcp://:7777/path":            fmt.Sprintf("tcp://%s:7777/path", DefaultHTTPHost),
-		"unix:///run/docker.sock":     "unix:///run/docker.sock",
-		"unix://":                     "unix://" + DefaultUnixSocket,
-		"fd://":                       "fd://",
-		"fd://something":              "fd://something",
-		"localhost:":                  "tcp://localhost:2375",
-		"localhost:5555":              "tcp://localhost:5555",
-		"localhost:5555/path":         "tcp://localhost:5555/path",
+		"0.0.0.1:":                "tcp://0.0.0.1:2375",
+		"0.0.0.1:5555":            "tcp://0.0.0.1:5555",
+		"[::1]:":                  "tcp://[::1]:2375",
+		"[0:0:0:0:0:0:0:1]:":      "tcp://[0:0:0:0:0:0:0:1]:2375",
+		":6666":                   fmt.Sprintf("tcp://%s:6666", DefaultHTTPHost),
+		"tcp://":                  DefaultTCPHost,
+		"tcp://:7777":             fmt.Sprintf("tcp://%s:7777", DefaultHTTPHost),
+		"unix:///run/docker.sock": "unix:///run/docker.sock",
+		"unix://":                 "unix://" + DefaultUnixSocket,
+		"fd://":                   "fd://",
+		"fd://something":          "fd://something",
+		"localhost:":              "tcp://localhost:2375",
+		"localhost:5555":          "tcp://localhost:5555",
 	}
 	for invalidAddr, expectedError := range invalids {
 		if addr, err := parseDaemonHost(invalidAddr); err == nil || expectedError != "" && err.Error() != expectedError {
@@ -99,30 +106,30 @@ func TestParseTCP(t *testing.T) {
 		defaultHTTPHost = "tcp://127.0.0.1:2376"
 	)
 	invalids := map[string]string{
-		"tcp:a.b.c.d":          "",
-		"tcp:a.b.c.d/path":     "",
-		"udp://127.0.0.1":      "Invalid proto, expected tcp: udp://127.0.0.1",
-		"udp://127.0.0.1:2375": "Invalid proto, expected tcp: udp://127.0.0.1:2375",
+		"tcp:a.b.c.d":                 "",
+		"tcp:a.b.c.d/path":            "",
+		"udp://127.0.0.1":             "Invalid proto, expected tcp: udp://127.0.0.1",
+		"udp://127.0.0.1:2375":        "Invalid proto, expected tcp: udp://127.0.0.1:2375",
+		":5555/path":                  "invalid bind address (:5555/path): should not contain a path element",
+		"0.0.0.1:5555/path":           "invalid bind address (0.0.0.1:5555/path): should not contain a path element",
+		"[::1]:5555/path":             "invalid bind address ([::1]:5555/path): should not contain a path element",
+		"[0:0:0:0:0:0:0:1]:5555/path": "invalid bind address ([0:0:0:0:0:0:0:1]:5555/path): should not contain a path element",
+		"tcp://:5555/path":            "invalid bind address (tcp://:5555/path): should not contain a path element",
+		"localhost:5555/path":         "invalid bind address (localhost:5555/path): should not contain a path element",
 	}
 	valids := map[string]string{
-		"":                            defaultHTTPHost,
-		"tcp://":                      defaultHTTPHost,
-		"0.0.0.1:":                    "tcp://0.0.0.1:2376",
-		"0.0.0.1:5555":                "tcp://0.0.0.1:5555",
-		"0.0.0.1:5555/path":           "tcp://0.0.0.1:5555/path",
-		":6666":                       "tcp://127.0.0.1:6666",
-		":6666/path":                  "tcp://127.0.0.1:6666/path",
-		"tcp://:7777":                 "tcp://127.0.0.1:7777",
-		"tcp://:7777/path":            "tcp://127.0.0.1:7777/path",
-		"[::1]:":                      "tcp://[::1]:2376",
-		"[::1]:5555":                  "tcp://[::1]:5555",
-		"[::1]:5555/path":             "tcp://[::1]:5555/path",
-		"[0:0:0:0:0:0:0:1]:":          "tcp://[0:0:0:0:0:0:0:1]:2376",
-		"[0:0:0:0:0:0:0:1]:5555":      "tcp://[0:0:0:0:0:0:0:1]:5555",
-		"[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
-		"localhost:":                  "tcp://localhost:2376",
-		"localhost:5555":              "tcp://localhost:5555",
-		"localhost:5555/path":         "tcp://localhost:5555/path",
+		"":                       defaultHTTPHost,
+		"tcp://":                 defaultHTTPHost,
+		"0.0.0.1:":               "tcp://0.0.0.1:2376",
+		"0.0.0.1:5555":           "tcp://0.0.0.1:5555",
+		":6666":                  "tcp://127.0.0.1:6666",
+		"tcp://:7777":            "tcp://127.0.0.1:7777",
+		"[::1]:":                 "tcp://[::1]:2376",
+		"[::1]:5555":             "tcp://[::1]:5555",
+		"[0:0:0:0:0:0:0:1]:":     "tcp://[0:0:0:0:0:0:0:1]:2376",
+		"[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555",
+		"localhost:":             "tcp://localhost:2376",
+		"localhost:5555":         "tcp://localhost:5555",
 	}
 	for invalidAddr, expectedError := range invalids {
 		if addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || expectedError != "" && err.Error() != expectedError {