randomize the serialization order of control frames (#4069)

* randomize the serialization order of control frames

* add comment for packetPacker.appendPacketPayload
This commit is contained in:
Marten Seemann 2023-09-11 11:49:29 +07:00 committed by GitHub
parent abfe1ef548
commit a7f807856c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,9 +1,13 @@
package quic
import (
crand "crypto/rand"
"encoding/binary"
"errors"
"fmt"
"golang.org/x/exp/rand"
"github.com/quic-go/quic-go/internal/ackhandler"
"github.com/quic-go/quic-go/internal/handshake"
"github.com/quic-go/quic-go/internal/protocol"
@ -122,6 +126,7 @@ type packetPacker struct {
acks ackFrameSource
datagramQueue *datagramQueue
retransmissionQueue *retransmissionQueue
rand rand.Rand
numNonAckElicitingAcks int
}
@ -140,6 +145,9 @@ func newPacketPacker(
datagramQueue *datagramQueue,
perspective protocol.Perspective,
) *packetPacker {
var b [8]byte
_, _ = crand.Read(b[:])
return &packetPacker{
cryptoSetup: cryptoSetup,
getDestConnID: getDestConnID,
@ -151,6 +159,7 @@ func newPacketPacker(
perspective: perspective,
framer: framer,
acks: acks,
rand: *rand.New(rand.NewSource(binary.BigEndian.Uint64(b[:]))),
pnManager: packetNumberManager,
}
}
@ -832,6 +841,8 @@ func (p *packetPacker) appendShortHeaderPacket(
}, nil
}
// appendPacketPayload serializes the payload of a packet into the raw byte slice.
// It modifies the order of payload.frames.
func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen protocol.ByteCount, v protocol.VersionNumber) ([]byte, error) {
payloadOffset := len(raw)
if pl.ack != nil {
@ -844,6 +855,11 @@ func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen pr
if paddingLen > 0 {
raw = append(raw, make([]byte, paddingLen)...)
}
// Randomize the order of the control frames.
// This makes sure that the receiver doesn't rely on the order in which frames are packed.
if len(pl.frames) > 1 {
p.rand.Shuffle(len(pl.frames), func(i, j int) { pl.frames[i], pl.frames[j] = pl.frames[j], pl.frames[i] })
}
for _, f := range pl.frames {
var err error
raw, err = f.Frame.Append(raw, v)