summaryrefslogtreecommitdiff
path: root/libpod/container_internal.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_internal.go')
-rw-r--r--libpod/container_internal.go126
1 files changed, 102 insertions, 24 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 43f5398a2..4bf15be86 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -39,6 +39,7 @@ import (
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
)
const (
@@ -290,7 +291,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err
// setup slirp4netns again because slirp4netns will die when conmon exits
if c.config.NetMode.IsSlirp4netns() {
- err := c.runtime.setupSlirp4netns(c)
+ err := c.runtime.setupSlirp4netns(c, c.state.NetNS)
if err != nil {
return false, err
}
@@ -299,7 +300,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err
// setup rootlesskit port forwarder again since it dies when conmon exits
// we use rootlesskit port forwarder only as rootless and when bridge network is used
if rootless.IsRootless() && c.config.NetMode.IsBridge() && len(c.config.PortMappings) > 0 {
- err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS.Path())
+ err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS.Path(), c.state.NetworkStatus)
if err != nil {
return false, err
}
@@ -445,10 +446,24 @@ func (c *Container) setupStorage(ctx context.Context) error {
},
LabelOpts: c.config.LabelOpts,
}
- if c.restoreFromCheckpoint && !c.config.Privileged {
- // If restoring from a checkpoint, the root file-system
- // needs to be mounted with the same SELinux labels as
- // it was mounted previously.
+
+ nopts := len(c.config.StorageOpts)
+ if nopts > 0 {
+ options.StorageOpt = make(map[string]string, nopts)
+ for _, opt := range c.config.StorageOpts {
+ split2 := strings.SplitN(opt, "=", 2)
+ if len(split2) > 2 {
+ return errors.Wrapf(define.ErrInvalidArg, "invalid storage options %q for %s", opt, c.ID())
+ }
+ options.StorageOpt[split2[0]] = split2[1]
+ }
+ }
+ if c.restoreFromCheckpoint && c.config.ProcessLabel != "" && c.config.MountLabel != "" {
+ // If restoring from a checkpoint, the root file-system needs
+ // to be mounted with the same SELinux labels as it was mounted
+ // previously. But only if both labels have been set. For
+ // privileged containers or '--ipc host' only ProcessLabel will
+ // be set and so we will skip it for cases like that.
if options.Flags == nil {
options.Flags = make(map[string]interface{})
}
@@ -482,9 +497,27 @@ func (c *Container) setupStorage(ctx context.Context) error {
c.setupStorageMapping(&options.IDMappingOptions, &c.config.IDMappings)
- containerInfo, err := c.runtime.storageService.CreateContainerStorage(ctx, c.runtime.imageContext, c.config.RootfsImageName, c.config.RootfsImageID, c.config.Name, c.config.ID, options)
- if err != nil {
- return errors.Wrapf(err, "error creating container storage")
+ // Unless the user has specified a name, use a randomly generated one.
+ // Note that name conflicts may occur (see #11735), so we need to loop.
+ generateName := c.config.Name == ""
+ var containerInfo ContainerInfo
+ var containerInfoErr error
+ for {
+ if generateName {
+ name, err := c.runtime.generateName()
+ if err != nil {
+ return err
+ }
+ c.config.Name = name
+ }
+ containerInfo, containerInfoErr = c.runtime.storageService.CreateContainerStorage(ctx, c.runtime.imageContext, c.config.RootfsImageName, c.config.RootfsImageID, c.config.Name, c.config.ID, options)
+
+ if !generateName || errors.Cause(containerInfoErr) != storage.ErrDuplicateName {
+ break
+ }
+ }
+ if containerInfoErr != nil {
+ return errors.Wrapf(containerInfoErr, "error creating container storage")
}
// only reconfig IDMappings if layer was mounted from storage
@@ -653,6 +686,19 @@ func (c *Container) refresh() error {
c.state.NetworkStatus = nil
c.state.NetworkStatusOld = nil
+ // Rewrite the config if necessary.
+ // Podman 4.0 uses a new port format in the config.
+ // getContainerConfigFromDB() already converted the old ports to the new one
+ // but it did not write the config to the db back for performance reasons.
+ // If a rewrite must happen the config.rewrite field is set to true.
+ if c.config.rewrite {
+ // SafeRewriteContainerConfig must be used with care. Make sure to not change config fields by accident.
+ if err := c.runtime.state.SafeRewriteContainerConfig(c, "", "", c.config); err != nil {
+ return errors.Wrapf(err, "failed to rewrite the config for container %s", c.config.ID)
+ }
+ c.config.rewrite = false
+ }
+
if err := c.save(); err != nil {
return errors.Wrapf(err, "error refreshing state for container %s", c.ID())
}
@@ -954,9 +1000,6 @@ func (c *Container) completeNetworkSetup() error {
if err := c.syncContainer(); err != nil {
return err
}
- if c.config.NetMode.IsSlirp4netns() {
- return c.runtime.setupSlirp4netns(c)
- }
if err := c.runtime.setupNetNS(c); err != nil {
return err
}
@@ -1046,7 +1089,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
}
// With the spec complete, do an OCI create
- if err := c.ociRuntime.CreateContainer(c, nil); err != nil {
+ if _, err = c.ociRuntime.CreateContainer(c, nil); err != nil {
// Fedora 31 is carrying a patch to display improved error
// messages to better handle the V2 transition. This is NOT
// upstream in any OCI runtime.
@@ -1499,8 +1542,8 @@ func (c *Container) mountStorage() (_ string, deferredErr error) {
mountPoint := c.config.Rootfs
// Check if overlay has to be created on top of Rootfs
if c.config.RootfsOverlay {
- overlayDest := c.runtime.store.GraphRoot()
- contentDir, err := overlay.GenerateStructure(c.runtime.store.GraphRoot(), c.ID(), "rootfs", c.RootUID(), c.RootGID())
+ overlayDest := c.runtime.RunRoot()
+ contentDir, err := overlay.GenerateStructure(overlayDest, c.ID(), "rootfs", c.RootUID(), c.RootGID())
if err != nil {
return "", errors.Wrapf(err, "rootfs-overlay: failed to create TempDir in the %s directory", overlayDest)
}
@@ -1550,14 +1593,49 @@ func (c *Container) mountStorage() (_ string, deferredErr error) {
}()
}
+ rootUID, rootGID := c.RootUID(), c.RootGID()
+
+ dirfd, err := unix.Open(mountPoint, unix.O_RDONLY|unix.O_PATH, 0)
+ if err != nil {
+ return "", errors.Wrap(err, "open mount point")
+ }
+ defer unix.Close(dirfd)
+
+ err = unix.Mkdirat(dirfd, "etc", 0755)
+ if err != nil && !os.IsExist(err) {
+ return "", errors.Wrap(err, "create /etc")
+ }
+ // If the etc directory was created, chown it to root in the container
+ if err == nil && (rootUID != 0 || rootGID != 0) {
+ err = unix.Fchownat(dirfd, "etc", rootUID, rootGID, unix.AT_SYMLINK_NOFOLLOW)
+ if err != nil {
+ return "", errors.Wrap(err, "chown /etc")
+ }
+ }
+
+ etcInTheContainerPath, err := securejoin.SecureJoin(mountPoint, "etc")
+ if err != nil {
+ return "", errors.Wrap(err, "resolve /etc in the container")
+ }
+
+ etcInTheContainerFd, err := unix.Open(etcInTheContainerPath, unix.O_RDONLY|unix.O_PATH, 0)
+ if err != nil {
+ return "", errors.Wrap(err, "open /etc in the container")
+ }
+ defer unix.Close(etcInTheContainerFd)
+
// If /etc/mtab does not exist in container image, then we need to
// create it, so that mount command within the container will work.
- mtab := filepath.Join(mountPoint, "/etc/mtab")
- if err := idtools.MkdirAllAs(filepath.Dir(mtab), 0755, c.RootUID(), c.RootGID()); err != nil {
- return "", errors.Wrap(err, "error creating mtab directory")
+ err = unix.Symlinkat("/proc/mounts", etcInTheContainerFd, "mtab")
+ if err != nil && !os.IsExist(err) {
+ return "", errors.Wrap(err, "creating /etc/mtab symlink")
}
- if err = os.Symlink("/proc/mounts", mtab); err != nil && !os.IsExist(err) {
- return "", err
+ // If the symlink was created, then also chown it to root in the container
+ if err == nil && (rootUID != 0 || rootGID != 0) {
+ err = unix.Fchownat(etcInTheContainerFd, "mtab", rootUID, rootGID, unix.AT_SYMLINK_NOFOLLOW)
+ if err != nil {
+ return "", errors.Wrap(err, "chown /etc/mtab")
+ }
}
// Request a mount of all named volumes
@@ -1725,11 +1803,11 @@ func (c *Container) cleanupStorage() error {
// umount rootfs overlay if it was created
if c.config.RootfsOverlay {
- overlayBasePath := filepath.Dir(c.config.StaticDir)
- overlayBasePath = filepath.Join(overlayBasePath, "rootfs")
+ overlayBasePath := filepath.Dir(c.state.Mountpoint)
if err := overlay.Unmount(overlayBasePath); err != nil {
- // If the container can't remove content report the error
- logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err)
+ if cleanupErr != nil {
+ logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err)
+ }
cleanupErr = err
}
}