mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-21 08:44:26 +00:00
SS2022 inbound: Fix data races and duplicate acceptance when decoding one UDP session concurrently
Packets of one client session can be processed by two inbound workers at the same time (e.g. the client's old and new source address after a NAT rebinding). The sliding window was checked and updated in two separate critical sections, and clientBodyCipher and the session's User were read without the lock, so the same packet ID could be accepted more than once and go test -race reported data races. Re-check the window and publish the cached body cipher in one critical section after the packet is fully validated, and always initialize the session's User under the lock.
This commit is contained in:
@@ -229,7 +229,9 @@ func (c *UDPCodec) DecodePacket(data []byte) (DecodedUDPPacket, error) {
|
||||
return DecodedUDPPacket{}, ErrBadHeaderType
|
||||
}
|
||||
|
||||
sessionItem.AddPacketID(packetID)
|
||||
if !sessionItem.CommitPacketID(packetID) {
|
||||
return DecodedUDPPacket{}, ErrPacketIdNotUnique
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
|
||||
@@ -248,8 +250,7 @@ func (c *UDPCodec) DecodePacket(data []byte) (DecodedUDPPacket, error) {
|
||||
}
|
||||
|
||||
func (s *ServerUDPSession) DecryptAESPayload(method *CipherMethod, psk []byte, sessionID, packetID uint64, rawHeader, bodyCipher []byte) (DecodedUDPPacket, error) {
|
||||
bodyAead := s.clientBodyCipher
|
||||
isNewCipher := false
|
||||
bodyAead := s.getClientBodyCipher()
|
||||
if bodyAead == nil {
|
||||
bodyKey := DeriveSessionSubKey(psk, rawHeader[:8], method.KeySaltLength)
|
||||
var err error
|
||||
@@ -257,7 +258,6 @@ func (s *ServerUDPSession) DecryptAESPayload(method *CipherMethod, psk []byte, s
|
||||
if err != nil {
|
||||
return DecodedUDPPacket{}, err
|
||||
}
|
||||
isNewCipher = true
|
||||
}
|
||||
|
||||
bodyNonce := rawHeader[4:16]
|
||||
@@ -275,10 +275,8 @@ func (s *ServerUDPSession) DecryptAESPayload(method *CipherMethod, psk []byte, s
|
||||
return DecodedUDPPacket{}, ErrBadHeaderType
|
||||
}
|
||||
|
||||
s.AddPacketID(packetID)
|
||||
|
||||
if isNewCipher {
|
||||
s.clientBodyCipher = bodyAead
|
||||
if !s.commitClientPacket(packetID, bodyAead) {
|
||||
return DecodedUDPPacket{}, ErrPacketIdNotUnique
|
||||
}
|
||||
|
||||
return decoded, nil
|
||||
|
||||
Reference in New Issue
Block a user