From 913f68ce3820801e045632cb05c6f11e0df50b47 Mon Sep 17 00:00:00 2001 From: Haichao Liu Date: Wed, 18 Nov 2020 20:53:22 +0800 Subject: [PATCH] device: add write queue mutex for peer fix panic: send on closed channel when remove peer Signed-off-by: Haichao Liu Signed-off-by: Jason A. Donenfeld --- device/peer.go | 6 +++++- device/receive.go | 2 ++ device/send.go | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/device/peer.go b/device/peer.go index ef6c010..78204bb 100644 --- a/device/peer.go +++ b/device/peer.go @@ -58,6 +58,7 @@ type Peer struct { } queue struct { + sync.RWMutex nonce chan *QueueOutboundElement // nonce / pre-handshake queue outbound chan *QueueOutboundElement // sequential ordering of work inbound chan *QueueInboundElement // sequential ordering of work @@ -195,10 +196,11 @@ func (peer *Peer) Start() { peer.routines.stopping.Add(PeerRoutineNumber) // prepare queues - + peer.queue.Lock() peer.queue.nonce = make(chan *QueueOutboundElement, QueueOutboundSize) peer.queue.outbound = make(chan *QueueOutboundElement, QueueOutboundSize) peer.queue.inbound = make(chan *QueueInboundElement, QueueInboundSize) + peer.queue.Unlock() peer.timersInit() peer.handshake.lastSentHandshake = time.Now().Add(-(RekeyTimeout + time.Second)) @@ -284,9 +286,11 @@ func (peer *Peer) Stop() { // close queues + peer.queue.Lock() close(peer.queue.nonce) close(peer.queue.outbound) close(peer.queue.inbound) + peer.queue.Unlock() peer.ZeroAndFlushAll() } diff --git a/device/receive.go b/device/receive.go index b53c9c0..e4a94b5 100644 --- a/device/receive.go +++ b/device/receive.go @@ -184,11 +184,13 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind conn.Bind) { // add to decryption queues + peer.queue.RLock() if peer.isRunning.Get() { if device.addToInboundAndDecryptionQueues(peer.queue.inbound, device.queue.decryption, elem) { buffer = device.GetMessageBuffer() } } + peer.queue.RUnlock() continue diff --git a/device/send.go b/device/send.go index c0bdba3..d202b62 100644 --- a/device/send.go +++ b/device/send.go @@ -107,6 +107,8 @@ func addToOutboundAndEncryptionQueues(outboundQueue chan *QueueOutboundElement, /* Queues a keepalive if no packets are queued for peer */ func (peer *Peer) SendKeepalive() bool { + peer.queue.RLock() + defer peer.queue.RUnlock() if len(peer.queue.nonce) != 0 || peer.queue.packetInNonceQueueIsAwaitingKey.Get() || !peer.isRunning.Get() { return false } @@ -310,6 +312,7 @@ func (device *Device) RoutineReadFromTUN() { // insert into nonce/pre-handshake queue + peer.queue.RLock() if peer.isRunning.Get() { if peer.queue.packetInNonceQueueIsAwaitingKey.Get() { peer.SendHandshakeInitiation(false) @@ -317,6 +320,7 @@ func (device *Device) RoutineReadFromTUN() { addToNonceQueue(peer.queue.nonce, elem, device) elem = nil } + peer.queue.RUnlock() } }