From 7a4c377bbb05b68e39c917c6a394885816504efa Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 15 Mar 2020 23:40:01 -0700 Subject: [PATCH] fix(keystore): avoid racy filesystem access Instead of checking then performing a file operation, perform the file operation and check the error. --- keystore/keystore.go | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/keystore/keystore.go b/keystore/keystore.go index 463f90e007e..a52b4ad1711 100644 --- a/keystore/keystore.go +++ b/keystore/keystore.go @@ -47,16 +47,13 @@ type FSKeystore struct { // NewFSKeystore returns a new filesystem-backed keystore. func NewFSKeystore(dir string) (*FSKeystore, error) { - _, err := os.Stat(dir) - if err != nil { - if !os.IsNotExist(err) { - return nil, err - } - if err := os.Mkdir(dir, 0700); err != nil { - return nil, err - } + err := os.Mkdir(dir, 0700) + switch { + case os.IsExist(err): + case err == nil: + default: + return nil, err } - return &FSKeystore{dir}, nil } @@ -91,15 +88,11 @@ func (ks *FSKeystore) Put(name string, k ci.PrivKey) error { kp := filepath.Join(ks.dir, name) - _, err = os.Stat(kp) - if err == nil { - return ErrKeyExists - } else if !os.IsNotExist(err) { - return err - } - - fi, err := os.Create(kp) + fi, err := os.OpenFile(kp, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) if err != nil { + if os.IsExist(err) { + err = ErrKeyExists + } return err } defer fi.Close()