Use secure temporary config files
This commit is contained in:
committed by
Brandon McGinty
parent
3ba5e03208
commit
dcffa1efa1
+15
-5
@@ -8,6 +8,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -61,15 +62,24 @@ func (c *Config) saveConfigLocked() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp := c.fn + ".tmp"
|
||||
if err := ioutil.WriteFile(tmp, data, 0600); err != nil {
|
||||
file, err := os.CreateTemp(filepath.Dir(c.fn), filepath.Base(c.fn)+".tmp-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(tmp, c.fn); err != nil {
|
||||
_ = os.Remove(tmp)
|
||||
tmp := file.Name()
|
||||
defer os.Remove(tmp)
|
||||
if err := file.Chmod(0600); err != nil {
|
||||
file.Close()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
if _, err := file.Write(data); err != nil {
|
||||
file.Close()
|
||||
return err
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmp, c.fn)
|
||||
}
|
||||
|
||||
func key(k uiterm.Key) *uiterm.Key {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -16,6 +17,25 @@ func TestSaveConfigReturnsWriteError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaveConfigDoesNotUsePredictableTemporaryPath(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "barnard.toml")
|
||||
legacyTemp := path + ".tmp"
|
||||
if err := os.WriteFile(legacyTemp, []byte("sentinel"), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cfg := NewConfig(&path)
|
||||
if err := cfg.SaveConfig(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
contents, err := os.ReadFile(legacyTemp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(contents) != "sentinel" {
|
||||
t.Fatalf("predictable temporary file was modified: %q", contents)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConcurrentConfigurationUpdatesAndWrites(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "barnard.toml")
|
||||
cfg := NewConfig(&path)
|
||||
|
||||
Reference in New Issue
Block a user