Skip to content

Commit

Permalink
quic: validate stream limits in transport params
Browse files Browse the repository at this point in the history
The maximum number of streams of a given type (bidi/uni)
is capped to 2^60, since a larger number would overflow
a varint.

Validate limits received in transport parameters.

RFC 9000, Section 4.6

For golang/go#58547

Change-Id: I7a4a15c569da91ad1b89a5dc71e1c5b213dbda9a
Reviewed-on: https://go-review.googlesource.com/c/net/+/524037
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
  • Loading branch information
neild committed Aug 29, 2023
1 parent d1b0a97 commit fe2abcb
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 3 deletions.
2 changes: 1 addition & 1 deletion internal/quic/packet_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ func consumeMaxStreamsFrame(b []byte) (typ streamType, max int64, n int) {
return 0, 0, -1
}
n += nn
if v > 1<<60 {
if v > maxStreamsLimit {
return 0, 0, -1
}
return typ, int64(v), n
Expand Down
4 changes: 4 additions & 0 deletions internal/quic/quic.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ const timerGranularity = 1 * time.Millisecond
// https://www.rfc-editor.org/rfc/rfc9000#section-14.1
const minimumClientInitialDatagramSize = 1200

// Maximum number of streams of a given type which may be created.
// https://www.rfc-editor.org/rfc/rfc9000.html#section-4.6-2
const maxStreamsLimit = 1 << 60

// A connSide distinguishes between the client and server sides of a connection.
type connSide int8

Expand Down
4 changes: 2 additions & 2 deletions internal/quic/stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1165,8 +1165,8 @@ func newTestConnAndRemoteStream(t *testing.T, side connSide, styp streamType, op

// permissiveTransportParameters may be passed as an option to newTestConn.
func permissiveTransportParameters(p *transportParameters) {
p.initialMaxStreamsBidi = maxVarint
p.initialMaxStreamsUni = maxVarint
p.initialMaxStreamsBidi = maxStreamsLimit
p.initialMaxStreamsUni = maxStreamsLimit
p.initialMaxData = maxVarint
p.initialMaxStreamDataBidiRemote = maxVarint
p.initialMaxStreamDataBidiLocal = maxVarint
Expand Down
6 changes: 6 additions & 0 deletions internal/quic/transport_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,14 @@ func unmarshalTransportParams(params []byte) (transportParameters, error) {
p.initialMaxStreamDataUni, n = consumeVarintInt64(val)
case paramInitialMaxStreamsBidi:
p.initialMaxStreamsBidi, n = consumeVarintInt64(val)
if p.initialMaxStreamsBidi > maxStreamsLimit {
return p, localTransportError(errTransportParameter)
}
case paramInitialMaxStreamsUni:
p.initialMaxStreamsUni, n = consumeVarintInt64(val)
if p.initialMaxStreamsUni > maxStreamsLimit {
return p, localTransportError(errTransportParameter)
}
case paramAckDelayExponent:
var v uint64
v, n = consumeVarint(val)
Expand Down
14 changes: 14 additions & 0 deletions internal/quic/transport_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,20 @@ func TestTransportParametersErrors(t *testing.T) {
15, // length
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
},
}, {
desc: "initial_max_streams_bidi is too large",
enc: []byte{
0x08, // initial_max_streams_bidi,
8, // length,
0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
},
}, {
desc: "initial_max_streams_uni is too large",
enc: []byte{
0x08, // initial_max_streams_uni,
9, // length,
0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
},
}, {
desc: "preferred_address is too short",
enc: []byte{
Expand Down

0 comments on commit fe2abcb

Please sign in to comment.