Skip to content

Commit

Permalink
libpod: create /etc/mtab safely
Browse files Browse the repository at this point in the history
make sure the /etc/mtab symlink is created inside the rootfs when /etc
is a symlink.

Closes: containers#12189

[NO NEW TESTS NEEDED] there is already a test case

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe authored and mheon committed Dec 6, 2021
1 parent 4ed07fb commit 579d91c
Showing 1 changed file with 41 additions and 5 deletions.
46 changes: 41 additions & 5 deletions libpod/container_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)

const (
Expand Down Expand Up @@ -1581,14 +1582,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
Expand Down

0 comments on commit 579d91c

Please sign in to comment.