From cecb41515d780213fd6b37bd04686f5296edf84c Mon Sep 17 00:00:00 2001
From: Josh Bleecher Snyder <josh@tailscale.com>
Date: Mon, 25 Jan 2021 09:35:35 -0800
Subject: [PATCH] device: serialize access to IpcSetOperation

Interleaves IpcSetOperations would spell trouble.

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
---
 device/device.go | 1 +
 device/uapi.go   | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/device/device.go b/device/device.go
index 58e996f..5d11766 100644
--- a/device/device.go
+++ b/device/device.go
@@ -23,6 +23,7 @@ type Device struct {
 	isUp     AtomicBool // device is (going) up
 	isClosed AtomicBool // device is closed? (acting as guard)
 	log      *Logger
+	ipcSetMu sync.Mutex // serializes UAPI set operations
 
 	// synchronized resources (locks acquired in order)
 
diff --git a/device/uapi.go b/device/uapi.go
index bf38459..c1ddb38 100644
--- a/device/uapi.go
+++ b/device/uapi.go
@@ -121,6 +121,9 @@ func (device *Device) IpcGetOperation(w io.Writer) error {
 // IpcSetOperation implements the WireGuard configuration protocol "set" operation.
 // See https://www.wireguard.com/xplatform/#configuration-protocol for details.
 func (device *Device) IpcSetOperation(r io.Reader) (err error) {
+	device.ipcSetMu.Lock()
+	defer device.ipcSetMu.Unlock()
+
 	defer func() {
 		if err != nil {
 			device.log.Error.Println(err)