mirror of
https://github.com/containers/podman.git
synced 2025-06-21 17:38:12 +08:00
Merge pull request #4074 from giuseppe/override-etc-passwd-group
execuser: look at the source for /etc/{passwd,group} overrides
This commit is contained in:
@ -181,6 +181,30 @@ func (c *Container) cleanupNetwork() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) getUserOverrides() *lookup.Overrides {
|
||||||
|
var hasPasswdFile, hasGroupFile bool
|
||||||
|
overrides := lookup.Overrides{}
|
||||||
|
for _, m := range c.config.Spec.Mounts {
|
||||||
|
if m.Destination == "/etc/passwd" {
|
||||||
|
overrides.ContainerEtcPasswdPath = m.Source
|
||||||
|
hasPasswdFile = true
|
||||||
|
}
|
||||||
|
if m.Destination == "/etc/group" {
|
||||||
|
overrides.ContainerEtcGroupPath = m.Source
|
||||||
|
hasGroupFile = true
|
||||||
|
}
|
||||||
|
if m.Destination == "/etc" {
|
||||||
|
if !hasPasswdFile {
|
||||||
|
overrides.ContainerEtcPasswdPath = filepath.Join(m.Source, "passwd")
|
||||||
|
}
|
||||||
|
if !hasGroupFile {
|
||||||
|
overrides.ContainerEtcGroupPath = filepath.Join(m.Source, "group")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &overrides
|
||||||
|
}
|
||||||
|
|
||||||
// Generate spec for a container
|
// Generate spec for a container
|
||||||
// Accepts a map of the container's dependencies
|
// Accepts a map of the container's dependencies
|
||||||
func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
||||||
@ -188,7 +212,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
|||||||
span.SetTag("type", "container")
|
span.SetTag("type", "container")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.config.User, nil)
|
overrides := c.getUserOverrides()
|
||||||
|
execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.config.User, overrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -200,13 +200,16 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
|
|||||||
pspec.Cwd = cwd
|
pspec.Cwd = cwd
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overrides := c.getUserOverrides()
|
||||||
|
execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, overrides)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// If user was set, look it up in the container to get a UID to use on
|
// If user was set, look it up in the container to get a UID to use on
|
||||||
// the host
|
// the host
|
||||||
if user != "" {
|
if user != "" {
|
||||||
execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sgids := make([]uint32, 0, len(execUser.Sgids))
|
sgids := make([]uint32, 0, len(execUser.Sgids))
|
||||||
for _, sgid := range execUser.Sgids {
|
for _, sgid := range execUser.Sgids {
|
||||||
sgids = append(sgids, uint32(sgid))
|
sgids = append(sgids, uint32(sgid))
|
||||||
@ -220,6 +223,17 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
|
|||||||
pspec.User = processUser
|
pspec.User = processUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasHomeSet := false
|
||||||
|
for _, s := range pspec.Env {
|
||||||
|
if strings.HasPrefix(s, "HOME=") {
|
||||||
|
hasHomeSet = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasHomeSet {
|
||||||
|
pspec.Env = append(pspec.Env, fmt.Sprintf("HOME=%s", execUser.Home))
|
||||||
|
}
|
||||||
|
|
||||||
processJSON, err := json.Marshal(pspec)
|
processJSON, err := json.Marshal(pspec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -29,17 +29,30 @@ func GetUserGroupInfo(containerMount, containerUser string, override *Overrides)
|
|||||||
defaultExecUser *user.ExecUser
|
defaultExecUser *user.ExecUser
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
passwdPath := etcpasswd
|
|
||||||
groupPath := etcgroup
|
|
||||||
|
|
||||||
if override != nil {
|
if override != nil {
|
||||||
// Check for an override /etc/passwd path
|
// Check for an override /etc/passwd path
|
||||||
if override.ContainerEtcPasswdPath != "" {
|
if override.ContainerEtcPasswdPath != "" {
|
||||||
passwdPath = override.ContainerEtcPasswdPath
|
passwdDest = override.ContainerEtcPasswdPath
|
||||||
}
|
}
|
||||||
// Check for an override for /etc/group path
|
// Check for an override for /etc/group path
|
||||||
if override.ContainerEtcGroupPath != "" {
|
if override.ContainerEtcGroupPath != "" {
|
||||||
groupPath = override.ContainerEtcGroupPath
|
groupDest = override.ContainerEtcGroupPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if passwdDest == "" {
|
||||||
|
// Make sure the /etc/passwd destination is not a symlink to something naughty
|
||||||
|
if passwdDest, err = securejoin.SecureJoin(containerMount, etcpasswd); err != nil {
|
||||||
|
logrus.Debug(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if groupDest == "" {
|
||||||
|
// Make sure the /etc/group destination is not a symlink to something naughty
|
||||||
|
if groupDest, err = securejoin.SecureJoin(containerMount, etcgroup); err != nil {
|
||||||
|
logrus.Debug(err)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,15 +69,6 @@ func GetUserGroupInfo(containerMount, containerUser string, override *Overrides)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the /etc/group and /etc/passwd destinations are not a symlink to something naughty
|
|
||||||
if passwdDest, err = securejoin.SecureJoin(containerMount, passwdPath); err != nil {
|
|
||||||
logrus.Debug(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if groupDest, err = securejoin.SecureJoin(containerMount, groupPath); err != nil {
|
|
||||||
logrus.Debug(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return user.GetExecUserPath(containerUser, defaultExecUser, passwdDest, groupDest)
|
return user.GetExecUserPath(containerUser, defaultExecUser, passwdDest, groupDest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +200,12 @@ var _ = Describe("Podman run", func() {
|
|||||||
match, _ := session.GrepString("/root")
|
match, _ := session.GrepString("/root")
|
||||||
Expect(match).Should(BeTrue())
|
Expect(match).Should(BeTrue())
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"run", "--rm", "--user", "2", ALPINE, "printenv", "HOME"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
match, _ = session.GrepString("/sbin")
|
||||||
|
Expect(match).Should(BeTrue())
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"run", "--rm", "--env", "HOME=/foo", ALPINE, "printenv", "HOME"})
|
session = podmanTest.Podman([]string{"run", "--rm", "--env", "HOME=/foo", ALPINE, "printenv", "HOME"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Reference in New Issue
Block a user