Fix race condition in sequence validation and invalidation. Once they are now checked, they can be immediately invalidated.

This commit is contained in:
Kleissner
2021-04-20 17:20:55 +02:00
parent 8269219cf0
commit 0dd9ef028b
2 changed files with 20 additions and 13 deletions

View File

@@ -91,7 +91,7 @@ func msgArbitrarySequence(publicKey *btcec.PublicKey) (sequence uint32) {
}
// msgValidateSequence validates the sequence number of an incoming message
func msgValidateSequence(raw *MessageRaw) (valid bool, rtt time.Duration) {
func msgValidateSequence(raw *MessageRaw, invalidate bool) (valid bool, rtt time.Duration) {
// Only Response and Pong
if raw.Command != CommandResponse && raw.Command != CommandPong {
return true, rtt
@@ -116,8 +116,11 @@ func msgValidateSequence(raw *MessageRaw) (valid bool, rtt time.Duration) {
sequence.counter++
// Special case CommandResponse: Extend validity in case there are follow-up responses by half of the round-trip time since they will be sent one-way.
if raw.Command == CommandResponse {
// invalidate the sequence immediately?
if invalidate {
delete(sequences, key)
} else if raw.Command == CommandResponse {
// Special case CommandResponse: Extend validity in case there are follow-up responses by half of the round-trip time since they will be sent one-way.
sequence.expires = time.Now().Add(time.Duration(ReplyTimeout) * time.Second / 2)
}

View File

@@ -158,14 +158,6 @@ func packetWorker(packets <-chan networkWire) {
// process the packet
raw := &MessageRaw{SenderPublicKey: senderPublicKey, PacketRaw: *decoded, connection: connection}
// Response, Pong: Validate sequence number which prevents unsolicited responses.
if valid, rtt := msgValidateSequence(raw); !valid {
log.Printf("packetWorker message with invalid sequence %d command %d from %s\n", raw.Sequence, raw.Command, raw.connection.Address.String()) // Only log for debug purposes.
continue
} else if rtt > 0 {
connection.RoundTripTime = rtt
}
switch decoded.Command {
case CommandAnnouncement: // Announce
if announce, _ := msgDecodeAnnouncement(raw); announce != nil {
@@ -174,8 +166,12 @@ func packetWorker(packets <-chan networkWire) {
case CommandResponse: // Response
if response, _ := msgDecodeResponse(raw); response != nil {
if (response.Actions & (1 << ActionSequenceLast)) > 0 {
msgInvalidateSequence(raw)
// Validate sequence number which prevents unsolicited responses.
if valid, rtt := msgValidateSequence(raw, response.Actions&(1<<ActionSequenceLast) > 0); !valid {
log.Printf("packetWorker message with invalid sequence %d command %d from %s\n", raw.Sequence, raw.Command, raw.connection.Address.String()) // Only log for debug purposes.
continue
} else if rtt > 0 {
connection.RoundTripTime = rtt
}
peer.cmdResponse(response)
@@ -190,6 +186,14 @@ func packetWorker(packets <-chan networkWire) {
peer.cmdPing(raw)
case CommandPong: // Ping
// Validate sequence number which prevents unsolicited responses.
if valid, rtt := msgValidateSequence(raw, true); !valid {
log.Printf("packetWorker message with invalid sequence %d command %d from %s\n", raw.Sequence, raw.Command, raw.connection.Address.String()) // Only log for debug purposes.
continue
} else if rtt > 0 {
connection.RoundTripTime = rtt
}
peer.cmdPong(raw)
case CommandChat: // Chat [debug]