diff options
Diffstat (limited to 'libpod/container_internal_linux.go')
-rw-r--r-- | libpod/container_internal_linux.go | 92 |
1 files changed, 74 insertions, 18 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index b25645e5c..0a1784ba7 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -12,15 +12,19 @@ import ( "path" "path/filepath" "strings" + "sync" "syscall" "time" cnitypes "github.com/containernetworking/cni/pkg/types/current" + "github.com/containernetworking/plugins/pkg/ns" crioAnnotations "github.com/containers/libpod/pkg/annotations" "github.com/containers/libpod/pkg/chrootuser" "github.com/containers/libpod/pkg/criu" "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage/pkg/idtools" + "github.com/cyphar/filepath-securejoin" + "github.com/opencontainers/runc/libcontainer/user" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/selinux/go-selinux/label" @@ -49,24 +53,61 @@ func (c *Container) unmountSHM(mount string) error { // prepare mounts the container and sets up other required resources like net // namespaces func (c *Container) prepare() (err error) { + var ( + wg sync.WaitGroup + netNS ns.NetNS + networkStatus []*cnitypes.Result + createNetNSErr, mountStorageErr error + mountPoint string + saveNetworkStatus bool + ) + + wg.Add(2) + + go func() { + defer wg.Done() + // Set up network namespace if not already set up + if c.config.CreateNetNS && c.state.NetNS == nil && !c.config.PostConfigureNetNS { + saveNetworkStatus = true + netNS, networkStatus, createNetNSErr = c.runtime.createNetNS(c) + } + }() // Mount storage if not mounted - if err := c.mountStorage(); err != nil { - return err - } + go func() { + defer wg.Done() + mountPoint, mountStorageErr = c.mountStorage() + }() - // Set up network namespace if not already set up - if c.config.CreateNetNS && c.state.NetNS == nil && !c.config.PostConfigureNetNS { - if err := c.runtime.createNetNS(c); err != nil { - // Tear down storage before exiting to make sure we - // don't leak mounts - if err2 := c.cleanupStorage(); err2 != nil { - logrus.Errorf("Error cleaning up storage for container %s: %v", c.ID(), err2) - } - return err + wg.Wait() + if createNetNSErr != nil { + if mountStorageErr != nil { + logrus.Error(createNetNSErr) + return mountStorageErr } + return createNetNSErr + } + if mountStorageErr != nil { + return mountStorageErr } - return nil + // Assign NetNS attributes to container + if saveNetworkStatus { + c.state.NetNS = netNS + c.state.NetworkStatus = networkStatus + } + + // Finish up mountStorage + c.state.Mounted = true + c.state.Mountpoint = mountPoint + if c.state.UserNSRoot == "" { + c.state.RealMountpoint = c.state.Mountpoint + } else { + c.state.RealMountpoint = filepath.Join(c.state.UserNSRoot, "mountpoint") + } + + logrus.Debugf("Created root filesystem for container %s at %s", c.ID(), c.state.Mountpoint) + // Save the container + return c.save() } // cleanupNetwork unmounts and cleans up the container's network @@ -104,7 +145,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path()) } } - // Check if the spec file mounts contain the label Relabel flags z or Z. // If they do, relabel the source directory and then remove the option. for _, m := range g.Mounts() { @@ -197,12 +237,28 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // Look up and add groups the user belongs to, if a group wasn't directly specified if !rootless.IsRootless() && !strings.Contains(c.config.User, ":") { - groups, err := chrootuser.GetAdditionalGroupsForUser(c.state.Mountpoint, uint64(g.Config.Process.User.UID)) - if err != nil && errors.Cause(err) != chrootuser.ErrNoSuchUser { + var groupDest, passwdDest string + defaultExecUser := user.ExecUser{ + Uid: 0, + Gid: 0, + Home: "/", + } + + // Make sure the /etc/group and /etc/passwd destinations are not a symlink to something naughty + if groupDest, err = securejoin.SecureJoin(c.state.Mountpoint, "/etc/group"); err != nil { + logrus.Debug(err) return nil, err } - for _, gid := range groups { - g.AddProcessAdditionalGid(gid) + if passwdDest, err = securejoin.SecureJoin(c.state.Mountpoint, "/etc/passwd"); err != nil { + logrus.Debug(err) + return nil, err + } + execUser, err := user.GetExecUserPath(c.config.User, &defaultExecUser, passwdDest, groupDest) + if err != nil { + return nil, err + } + for _, gid := range execUser.Sgids { + g.AddProcessAdditionalGid(uint32(gid)) } } |