From a4a306d2a2850e26052c86c329dc2d1a0521f723 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Wed, 10 Jun 2020 13:54:21 -0700 Subject: [PATCH] Write state.json atomically We want to make sure that the state file is syned and cannot be read partially or truncated. Signed-off-by: Mrunal Patel --- libcontainer/container_linux.go | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 10e684b8..92bba2a7 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -1674,13 +1674,30 @@ func (c *linuxContainer) updateState(process parentProcess) (*State, error) { return state, nil } -func (c *linuxContainer) saveState(s *State) error { - f, err := os.Create(filepath.Join(c.root, stateFilename)) +func (c *linuxContainer) saveState(s *State) (retErr error) { + tmpFile, err := ioutil.TempFile(c.root, "state-") if err != nil { return err } - defer f.Close() - return utils.WriteJSON(f, s) + + defer func() { + if retErr != nil { + tmpFile.Close() + os.Remove(tmpFile.Name()) + } + }() + + err = utils.WriteJSON(tmpFile, s) + if err != nil { + return err + } + err = tmpFile.Close() + if err != nil { + return err + } + + stateFilePath := filepath.Join(c.root, stateFilename) + return os.Rename(tmpFile.Name(), stateFilePath) } func (c *linuxContainer) deleteState() error {