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
}
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 {
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]
}
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 := ""
var data *inspect.ImageData = nil
@ -171,12 +176,14 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container
return nil, nil, err
}
if c.String("cidfile") != "" {
err := libpod.WriteFile(ctr.ID(), c.String("cidfile"))
if cidFile != nil {
_, err = cidFile.WriteString(ctr.ID())
if err != nil {
logrus.Error(err)
}
}
logrus.Debugf("New container created %q", ctr.ID())
return ctr, createConfig, nil
}

View file

@ -90,13 +90,17 @@ func podCreateCmd(c *cli.Context) error {
}
defer runtime.Shutdown(false)
if c.IsSet("pod-id-file") {
if _, err = os.Stat(c.String("pod-id-file")); err == nil {
return errors.Errorf("pod id file exists. ensure another pod is not using it or delete %s", c.String("pod-id-file"))
var podIdFile *os.File
if c.IsSet("pod-id-file") && os.Geteuid() == 0 {
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 {
return errors.Wrapf(err, "unable to write pod id file %s", c.String("pod-id-file"))
if err != nil {
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") != "" {
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
}
if c.IsSet("pod-id-file") {
err = libpod.WriteFile(pod.ID(), c.String("pod-id-file"))
if podIdFile != nil {
_, err = podIdFile.WriteString(pod.ID())
if err != nil {
logrus.Error(err)
}

View file

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