ipn/ipnlocal: hold the mutex when in onTailnetDefaultAutoUpdate (#11786)

Turns out, profileManager is not safe for concurrent use and I missed
all the locking infrastructure in LocalBackend, oops.

I was not able to reproduce the race even with `go test -count 100`, but
this seems like an obvious fix.

Fixes #11773

Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
Andrew Lytvynov 2024-04-17 22:15:09 -05:00 committed by GitHub
parent 88a7767492
commit 22bd506129
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2498,6 +2498,9 @@ func (b *LocalBackend) onClientVersion(v *tailcfg.ClientVersion) {
}
func (b *LocalBackend) onTailnetDefaultAutoUpdate(au bool) {
unlock := b.lockAndGetUnlock()
defer unlock()
prefs := b.pm.CurrentPrefs()
if !prefs.Valid() {
b.logf("[unexpected]: received tailnet default auto-update callback but current prefs are nil")
@ -2511,12 +2514,12 @@ func (b *LocalBackend) onTailnetDefaultAutoUpdate(au bool) {
b.logf("using tailnet default auto-update setting: %v", au)
prefsClone := prefs.AsStruct()
prefsClone.AutoUpdate.Apply = opt.NewBool(au)
_, err := b.EditPrefs(&ipn.MaskedPrefs{
_, err := b.editPrefsLockedOnEntry(&ipn.MaskedPrefs{
Prefs: *prefsClone,
AutoUpdateSet: ipn.AutoUpdatePrefsMask{
ApplySet: true,
},
})
}, unlock)
if err != nil {
b.logf("failed to apply tailnet-wide default for auto-updates (%v): %v", au, err)
return