create: fix writing cidfile when using rootless

prevent opening the same file twice, since we re-exec podman in
rootless mode.  While at it, also solve a possible race between the
check for the file and writing to it.  Another process could have
created the file in the meanwhile and we would just end up overwriting
it.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2018-10-23 22:06:14 +02:00
parent 10bab99ea0
commit dfc689efc9
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED
3 changed files with 33 additions and 29 deletions

View File

@ -95,15 +95,6 @@ func createInit(c *cli.Context) error {
return err return err
} }
if c.String("cidfile") != "" {
if _, err := os.Stat(c.String("cidfile")); err == nil {
return errors.Errorf("container id file exists. ensure another container is not using it or delete %s", c.String("cidfile"))
}
if err := libpod.WriteFile("", c.String("cidfile")); err != nil {
return errors.Wrapf(err, "unable to write cidfile %s", c.String("cidfile"))
}
}
if len(c.Args()) < 1 { if len(c.Args()) < 1 {
return errors.Errorf("image name or ID is required") return errors.Errorf("image name or ID is required")
} }
@ -119,6 +110,20 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container
rootfs = c.Args()[0] rootfs = c.Args()[0]
} }
var err error
var cidFile *os.File
if c.IsSet("cidfile") && os.Geteuid() == 0 {
cidFile, err = libpod.OpenExclusiveFile(c.String("cidfile"))
if err != nil && os.IsExist(err) {
return nil, nil, errors.Errorf("container id file exists. Ensure another container is not using it or delete %s", c.String("cidfile"))
}
if err != nil {
return nil, nil, errors.Errorf("error opening cidfile %s", c.String("cidfile"))
}
defer cidFile.Close()
defer cidFile.Sync()
}
imageName := "" imageName := ""
var data *inspect.ImageData = nil var data *inspect.ImageData = nil
@ -171,12 +176,14 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container
return nil, nil, err return nil, nil, err
} }
if c.String("cidfile") != "" { if cidFile != nil {
err := libpod.WriteFile(ctr.ID(), c.String("cidfile")) _, err = cidFile.WriteString(ctr.ID())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }
} }
logrus.Debugf("New container created %q", ctr.ID()) logrus.Debugf("New container created %q", ctr.ID())
return ctr, createConfig, nil return ctr, createConfig, nil
} }

View File

@ -90,13 +90,17 @@ func podCreateCmd(c *cli.Context) error {
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if c.IsSet("pod-id-file") { var podIdFile *os.File
if _, err = os.Stat(c.String("pod-id-file")); err == nil { if c.IsSet("pod-id-file") && os.Geteuid() == 0 {
return errors.Errorf("pod id file exists. ensure another pod is not using it or delete %s", c.String("pod-id-file")) podIdFile, err = libpod.OpenExclusiveFile(c.String("pod-id-file"))
if err != nil && os.IsExist(err) {
return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.String("pod-id-file"))
} }
if err = libpod.WriteFile("", c.String("pod-id-file")); err != nil { if err != nil {
return errors.Wrapf(err, "unable to write pod id file %s", c.String("pod-id-file")) return errors.Errorf("error opening pod-id-file %s", c.String("pod-id-file"))
} }
defer podIdFile.Close()
defer podIdFile.Sync()
} }
if !c.BoolT("infra") && c.IsSet("share") && c.String("share") != "none" && c.String("share") != "" { if !c.BoolT("infra") && c.IsSet("share") && c.String("share") != "none" && c.String("share") != "" {
return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container") return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container")
@ -137,8 +141,8 @@ func podCreateCmd(c *cli.Context) error {
return err return err
} }
if c.IsSet("pod-id-file") { if podIdFile != nil {
err = libpod.WriteFile(pod.ID(), c.String("pod-id-file")) _, err = podIdFile.WriteString(pod.ID())
if err != nil { if err != nil {
logrus.Error(err) logrus.Error(err)
} }

View File

@ -24,22 +24,15 @@ const (
DefaultTransport = "docker://" DefaultTransport = "docker://"
) )
// WriteFile writes a provided string to a provided path // OpenExclusiveFile opens a file for writing and ensure it doesn't already exist
func WriteFile(content string, path string) error { func OpenExclusiveFile(path string) (*os.File, error) {
baseDir := filepath.Dir(path) baseDir := filepath.Dir(path)
if baseDir != "" { if baseDir != "" {
if _, err := os.Stat(baseDir); err != nil { if _, err := os.Stat(baseDir); err != nil {
return err return nil, err
} }
} }
f, err := os.Create(path) return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
if err != nil {
return err
}
defer f.Close()
f.WriteString(content)
f.Sync()
return nil
} }
// FuncTimer helps measure the execution time of a function // FuncTimer helps measure the execution time of a function