aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-01-07 15:56:52 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-01-07 17:08:41 +0100
commit29b04775856b62213d7bc01937641e2db081d707 (patch)
tree6044865a29772209154acd59ba7f66274a623403
parent85b495057977e12df378778366a03b508c43f00f (diff)
downloadwireguard-go-29b04775856b62213d7bc01937641e2db081d707.tar.gz
wireguard-go-29b04775856b62213d7bc01937641e2db081d707.zip
device: receive: drain decryption queue before exiting RoutineDecryption
It's possible for RoutineSequentialReceiver to try to lock an elem after RoutineDecryption has exited. Before this meant we didn't then unlock the elem, so the whole program deadlocked. As well, it looks like the flush code (which is now potentially unnecessary?) wasn't properly dropping the buffers for the not-already-dropped case. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--device/device.go5
-rw-r--r--device/receive.go15
2 files changed, 18 insertions, 2 deletions
diff --git a/device/device.go b/device/device.go
index 3172224..d37fe6f 100644
--- a/device/device.go
+++ b/device/device.go
@@ -371,7 +371,10 @@ func (device *Device) FlushPacketQueues() {
select {
case elem, ok := <-device.queue.decryption:
if ok {
- elem.Drop()
+ if !elem.IsDropped() {
+ elem.Drop()
+ device.PutMessageBuffer(elem.buffer)
+ }
}
case <-device.queue.handshake:
default:
diff --git a/device/receive.go b/device/receive.go
index 4b6f278..0bd22bf 100644
--- a/device/receive.go
+++ b/device/receive.go
@@ -251,7 +251,20 @@ func (device *Device) RoutineDecryption() {
for {
select {
case <-device.signals.stop:
- return
+ for {
+ select {
+ case elem, ok := <-device.queue.decryption:
+ if ok {
+ if !elem.IsDropped() {
+ elem.Drop()
+ device.PutMessageBuffer(elem.buffer)
+ }
+ elem.Unlock()
+ }
+ default:
+ return
+ }
+ }
case elem, ok := <-device.queue.decryption: