diff -Nru golang-1.11-1.11.12/debian/changelog golang-1.11-1.11.13/debian/changelog --- golang-1.11-1.11.12/debian/changelog 2019-08-13 08:23:17.000000000 +0000 +++ golang-1.11-1.11.13/debian/changelog 2019-08-15 20:58:37.000000000 +0000 @@ -1,8 +1,20 @@ -golang-1.11 (1.11.12-4~201908122347~delta2~ubuntu19.04.1) disco; urgency=low +golang-1.11 (1.11.13-1~201908151856~delta2~ubuntu19.04.1) disco; urgency=low * Auto build. - -- Launchpad Package Builder Tue, 13 Aug 2019 08:23:17 +0000 + -- Launchpad Package Builder Thu, 15 Aug 2019 20:58:37 +0000 + +golang-1.11 (1.11.13-1) unstable; urgency=medium + + * New upstream version 1.11.13 + - Fix Denial of Service vulnerabilities in the HTTP/2 implementation. + https://github.com/golang/go/issues/33631 + CVE-2019-9512, CVE-2019-9514 + - Fix multiple Parsing Issues in URL.Parse + https://github.com/golang/go/issues/29098 + CVE-2019-14809 + + -- Dr. Tobias Quathamer Thu, 15 Aug 2019 20:56:03 +0200 golang-1.11 (1.11.12-4) unstable; urgency=medium diff -Nru golang-1.11-1.11.12/debian/git-build-recipe.manifest golang-1.11-1.11.13/debian/git-build-recipe.manifest --- golang-1.11-1.11.12/debian/git-build-recipe.manifest 2019-08-13 08:23:17.000000000 +0000 +++ golang-1.11-1.11.13/debian/git-build-recipe.manifest 2019-08-15 20:58:37.000000000 +0000 @@ -1,2 +1,2 @@ -# git-build-recipe format 0.4 deb-version {debversion}~201908122347~delta2 -lp:~canonical-is-delta/golang/+git/golang-deb git-commit:fa2929af89a5b08775e67633086146eff0bee5f5 +# git-build-recipe format 0.4 deb-version {debversion}~201908151856~delta2 +lp:~canonical-is-delta/golang/+git/golang-deb git-commit:1753b89aa125530590cec4544023b144491f992e diff -Nru golang-1.11-1.11.12/doc/devel/release.html golang-1.11-1.11.13/doc/devel/release.html --- golang-1.11-1.11.12/doc/devel/release.html 2019-07-08 20:30:23.000000000 +0000 +++ golang-1.11-1.11.13/doc/devel/release.html 2019-08-13 16:50:08.000000000 +0000 @@ -120,6 +120,13 @@ 1.11.12 milestone on our issue tracker for details.

+

+go1.11.13 (released 2019/08/13) includes security fixes to the +net/http and net/url packages. +See the Go +1.11.13 milestone on our issue tracker for details. +

+

go1.10 (released 2018/02/16)

diff -Nru golang-1.11-1.11.12/src/net/http/h2_bundle.go golang-1.11-1.11.13/src/net/http/h2_bundle.go --- golang-1.11-1.11.12/src/net/http/h2_bundle.go 2019-07-08 20:30:24.000000000 +0000 +++ golang-1.11-1.11.13/src/net/http/h2_bundle.go 2019-08-13 16:50:13.000000000 +0000 @@ -3835,10 +3835,11 @@ } const ( - http2prefaceTimeout = 10 * time.Second - http2firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway - http2handlerChunkWriteSize = 4 << 10 - http2defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + http2prefaceTimeout = 10 * time.Second + http2firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway + http2handlerChunkWriteSize = 4 << 10 + http2defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + http2maxQueuedControlFrames = 10000 ) var ( @@ -3946,6 +3947,15 @@ return http2defaultMaxStreams } +// maxQueuedControlFrames is the maximum number of control frames like +// SETTINGS, PING and RST_STREAM that will be queued for writing before +// the connection is closed to prevent memory exhaustion attacks. +func (s *http2Server) maxQueuedControlFrames() int { + // TODO: if anybody asks, add a Server field, and remember to define the + // behavior of negative values. + return http2maxQueuedControlFrames +} + type http2serverInternalState struct { mu sync.Mutex activeConns map[*http2serverConn]struct{} @@ -4254,6 +4264,7 @@ sawFirstSettings bool // got the initial SETTINGS frame after the preface needToSendSettingsAck bool unackedSettings int // how many SETTINGS have we sent without ACKs? + queuedControlFrames int // control frames in the writeSched queue clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client curClientStreams uint32 // number of open streams initiated by the client @@ -4644,6 +4655,14 @@ } } + // If the peer is causing us to generate a lot of control frames, + // but not reading them from us, assume they are trying to make us + // run out of memory. + if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() { + sc.vlogf("http2: too many control frames in send queue, closing connection") + return + } + // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY // with no error code (graceful shutdown), don't start the timer until // all open streams have been completed. @@ -4845,6 +4864,14 @@ } if !ignoreWrite { + if wr.isControl() { + sc.queuedControlFrames++ + // For extra safety, detect wraparounds, which should not happen, + // and pull the plug. + if sc.queuedControlFrames < 0 { + sc.conn.Close() + } + } sc.writeSched.Push(wr) } sc.scheduleFrameWrite() @@ -4962,10 +4989,8 @@ // If a frame is already being written, nothing happens. This will be called again // when the frame is done being written. // -// If a frame isn't being written we need to send one, the best frame -// to send is selected, preferring first things that aren't -// stream-specific (e.g. ACKing settings), and then finding the -// highest priority stream. +// If a frame isn't being written and we need to send one, the best frame +// to send is selected by writeSched. // // If a frame isn't being written and there's nothing else to send, we // flush the write buffer. @@ -4993,6 +5018,9 @@ } if !sc.inGoAway || sc.goAwayCode == http2ErrCodeNo { if wr, ok := sc.writeSched.Pop(); ok { + if wr.isControl() { + sc.queuedControlFrames-- + } sc.startFrameWrite(wr) continue } @@ -5285,6 +5313,8 @@ if err := f.ForeachSetting(sc.processSetting); err != nil { return err } + // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be + // acknowledged individually, even if multiple are received before the ACK. sc.needToSendSettingsAck = true sc.scheduleFrameWrite() return nil @@ -9476,7 +9506,7 @@ // Pop dequeues the next frame to write. Returns false if no frames can // be written. Frames with a given wr.StreamID() are Pop'd in the same - // order they are Push'd. + // order they are Push'd. No frames should be discarded except by CloseStream. Pop() (wr http2FrameWriteRequest, ok bool) } @@ -9520,6 +9550,12 @@ return wr.stream.id } +// isControl reports whether wr is a control frame for MaxQueuedControlFrames +// purposes. That includes non-stream frames and RST_STREAM frames. +func (wr http2FrameWriteRequest) isControl() bool { + return wr.stream == nil +} + // DataSize returns the number of flow control bytes that must be consumed // to write this entire frame. This is 0 for non-DATA frames. func (wr http2FrameWriteRequest) DataSize() int { diff -Nru golang-1.11-1.11.12/src/net/http/transport.go golang-1.11-1.11.13/src/net/http/transport.go --- golang-1.11-1.11.12/src/net/http/transport.go 2019-07-08 20:30:24.000000000 +0000 +++ golang-1.11-1.11.13/src/net/http/transport.go 2019-08-13 16:50:13.000000000 +0000 @@ -640,6 +640,8 @@ } func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) { + // TODO: the validPort check is redundant after CL 189258, as url.URL.Port + // only returns valid ports now. golang.org/issue/33600 if port := treq.URL.Port(); !validPort(port) { return cm, fmt.Errorf("invalid URL port %q", port) } diff -Nru golang-1.11-1.11.12/src/net/http/transport_test.go golang-1.11-1.11.13/src/net/http/transport_test.go --- golang-1.11-1.11.12/src/net/http/transport_test.go 2019-07-08 20:30:24.000000000 +0000 +++ golang-1.11-1.11.13/src/net/http/transport_test.go 2019-08-13 16:50:13.000000000 +0000 @@ -4111,7 +4111,7 @@ t.Fatalf("got %#v; want *url.Error", err) } got := ue.Err.Error() - want := `invalid URL port "123foo"` + want := `invalid port ":123foo" after host` if got != want { t.Errorf("got error %q; want %q", got, want) } diff -Nru golang-1.11-1.11.12/src/net/url/url.go golang-1.11-1.11.13/src/net/url/url.go --- golang-1.11-1.11.12/src/net/url/url.go 2019-07-08 20:30:24.000000000 +0000 +++ golang-1.11-1.11.13/src/net/url/url.go 2019-08-13 16:50:13.000000000 +0000 @@ -636,6 +636,11 @@ } return host1 + host2 + host3, nil } + } else if i := strings.LastIndex(host, ":"); i != -1 { + colonPort := host[i:] + if !validOptionalPort(colonPort) { + return "", fmt.Errorf("invalid port %q after host", colonPort) + } } var err error @@ -1033,44 +1038,39 @@ return result } -// Hostname returns u.Host, without any port number. +// Hostname returns u.Host, stripping any valid port number if present. // -// If Host is an IPv6 literal with a port number, Hostname returns the -// IPv6 literal without the square brackets. IPv6 literals may include -// a zone identifier. +// If the result is enclosed in square brackets, as literal IPv6 addresses are, +// the square brackets are removed from the result. func (u *URL) Hostname() string { - return stripPort(u.Host) + host, _ := splitHostPort(u.Host) + return host } // Port returns the port part of u.Host, without the leading colon. -// If u.Host doesn't contain a port, Port returns an empty string. +// +// If u.Host doesn't contain a valid numeric port, Port returns an empty string. func (u *URL) Port() string { - return portOnly(u.Host) + _, port := splitHostPort(u.Host) + return port } -func stripPort(hostport string) string { - colon := strings.IndexByte(hostport, ':') - if colon == -1 { - return hostport - } - if i := strings.IndexByte(hostport, ']'); i != -1 { - return strings.TrimPrefix(hostport[:i], "[") - } - return hostport[:colon] -} +// splitHostPort separates host and port. If the port is not valid, it returns +// the entire input as host, and it doesn't check the validity of the host. +// Unlike net.SplitHostPort, but per RFC 3986, it requires ports to be numeric. +func splitHostPort(hostport string) (host, port string) { + host = hostport -func portOnly(hostport string) string { - colon := strings.IndexByte(hostport, ':') - if colon == -1 { - return "" - } - if i := strings.Index(hostport, "]:"); i != -1 { - return hostport[i+len("]:"):] + colon := strings.LastIndexByte(host, ':') + if colon != -1 && validOptionalPort(host[colon:]) { + host, port = host[:colon], host[colon+1:] } - if strings.Contains(hostport, "]") { - return "" + + if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") { + host = host[1 : len(host)-1] } - return hostport[colon+len(":"):] + + return } // Marshaling interface implementations. diff -Nru golang-1.11-1.11.12/src/net/url/url_test.go golang-1.11-1.11.13/src/net/url/url_test.go --- golang-1.11-1.11.12/src/net/url/url_test.go 2019-07-08 20:30:24.000000000 +0000 +++ golang-1.11-1.11.13/src/net/url/url_test.go 2019-08-13 16:50:13.000000000 +0000 @@ -422,10 +422,10 @@ }, // worst case host, still round trips { - "scheme://!$&'()*+,;=hello!:port/path", + "scheme://!$&'()*+,;=hello!:1/path", &URL{ Scheme: "scheme", - Host: "!$&'()*+,;=hello!:port", + Host: "!$&'()*+,;=hello!:1", Path: "/path", }, "", @@ -1420,11 +1420,13 @@ {"http://[::1]", false}, {"http://[::1]:80", false}, {"http://[::1]:namedport", true}, // rfc3986 3.2.3 + {"http://x:namedport", true}, // rfc3986 3.2.3 {"http://[::1]/", false}, {"http://[::1]a", true}, {"http://[::1]%23", true}, {"http://[::1%25en0]", false}, // valid zone id {"http://[::1]:", false}, // colon, but no port OK + {"http://x:", false}, // colon, but no port OK {"http://[::1]:%38%30", true}, // not allowed: % encoding only for non-ASCII {"http://[::1%25%41]", false}, // RFC 6874 allows over-escaping in zone {"http://[%10::1]", true}, // no %xx escapes in IP address @@ -1616,46 +1618,46 @@ } } -func TestURLHostname(t *testing.T) { +func TestURLHostnameAndPort(t *testing.T) { tests := []struct { - host string // URL.Host field - want string + in string // URL.Host field + host string + port string }{ - {"foo.com:80", "foo.com"}, - {"foo.com", "foo.com"}, - {"FOO.COM", "FOO.COM"}, // no canonicalization (yet?) - {"1.2.3.4", "1.2.3.4"}, - {"1.2.3.4:80", "1.2.3.4"}, - {"[1:2:3:4]", "1:2:3:4"}, - {"[1:2:3:4]:80", "1:2:3:4"}, - {"[::1]:80", "::1"}, + {"foo.com:80", "foo.com", "80"}, + {"foo.com", "foo.com", ""}, + {"foo.com:", "foo.com", ""}, + {"FOO.COM", "FOO.COM", ""}, // no canonicalization + {"1.2.3.4", "1.2.3.4", ""}, + {"1.2.3.4:80", "1.2.3.4", "80"}, + {"[1:2:3:4]", "1:2:3:4", ""}, + {"[1:2:3:4]:80", "1:2:3:4", "80"}, + {"[::1]:80", "::1", "80"}, + {"[::1]", "::1", ""}, + {"[::1]:", "::1", ""}, + {"localhost", "localhost", ""}, + {"localhost:443", "localhost", "443"}, + {"some.super.long.domain.example.org:8080", "some.super.long.domain.example.org", "8080"}, + {"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "17000"}, + {"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ""}, + + // Ensure that even when not valid, Host is one of "Hostname", + // "Hostname:Port", "[Hostname]" or "[Hostname]:Port". + // See https://golang.org/issue/29098. + {"[google.com]:80", "google.com", "80"}, + {"google.com]:80", "google.com]", "80"}, + {"google.com:80_invalid_port", "google.com:80_invalid_port", ""}, + {"[::1]extra]:80", "::1]extra", "80"}, + {"google.com]extra:extra", "google.com]extra:extra", ""}, } for _, tt := range tests { - u := &URL{Host: tt.host} - got := u.Hostname() - if got != tt.want { - t.Errorf("Hostname for Host %q = %q; want %q", tt.host, got, tt.want) + u := &URL{Host: tt.in} + host, port := u.Hostname(), u.Port() + if host != tt.host { + t.Errorf("Hostname for Host %q = %q; want %q", tt.in, host, tt.host) } - } -} - -func TestURLPort(t *testing.T) { - tests := []struct { - host string // URL.Host field - want string - }{ - {"foo.com", ""}, - {"foo.com:80", "80"}, - {"1.2.3.4", ""}, - {"1.2.3.4:80", "80"}, - {"[1:2:3:4]", ""}, - {"[1:2:3:4]:80", "80"}, - } - for _, tt := range tests { - u := &URL{Host: tt.host} - got := u.Port() - if got != tt.want { - t.Errorf("Port for Host %q = %q; want %q", tt.host, got, tt.want) + if port != tt.port { + t.Errorf("Port for Host %q = %q; want %q", tt.in, port, tt.port) } } } diff -Nru golang-1.11-1.11.12/VERSION golang-1.11-1.11.13/VERSION --- golang-1.11-1.11.12/VERSION 2019-07-08 20:30:32.000000000 +0000 +++ golang-1.11-1.11.13/VERSION 2019-08-13 16:52:38.000000000 +0000 @@ -1 +1 @@ -go1.11.12 \ No newline at end of file +go1.11.13 \ No newline at end of file