If newuidmap or newgidmap fail, then check their permissions

Often distributions to not have newuidmap and netgidmap configured
to be setuid. If Podman fails to setup the user namespace, check to
see if these files doe not have the proper protection and tell the user.

[NO NEW TESTS NEEDED]

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2022-04-08 10:51:39 -04:00
parent cdbc33112e
commit 2508913a0f
20 changed files with 133 additions and 101 deletions

View File

@@ -1,3 +1,4 @@
//go:build linux
// +build linux
package unshare
@@ -76,6 +77,28 @@ func getRootlessGID() int {
return os.Getegid()
}
// IsSetID checks if specified path has correct FileMode (Setuid|SETGID) or the
// matching file capabilitiy
func IsSetID(path string, modeid os.FileMode, capid capability.Cap) (bool, error) {
info, err := os.Stat(path)
if err != nil {
return false, err
}
mode := info.Mode()
if mode&modeid == modeid {
return true, nil
}
cap, err := capability.NewFile2(path)
if err != nil {
return false, err
}
if err := cap.Load(); err != nil {
return false, err
}
return cap.Get(capability.EFFECTIVE, capid), nil
}
func (c *Cmd) Start() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -215,15 +238,26 @@ func (c *Cmd) Start() error {
gidmapSet := false
// Set the GID map.
if c.UseNewgidmap {
cmd := exec.Command("newgidmap", append([]string{pidString}, strings.Fields(strings.Replace(g.String(), "\n", " ", -1))...)...)
path, err := exec.LookPath("newgidmap")
if err != nil {
return errors.Wrapf(err, "error finding newgidmap")
}
cmd := exec.Command(path, append([]string{pidString}, strings.Fields(strings.Replace(g.String(), "\n", " ", -1))...)...)
g.Reset()
cmd.Stdout = g
cmd.Stderr = g
err := cmd.Run()
if err == nil {
if err := cmd.Run(); err == nil {
gidmapSet = true
} else {
logrus.Warnf("Error running newgidmap: %v: %s", err, g.String())
isSetgid, err := IsSetID(path, os.ModeSetgid, capability.CAP_SETGID)
if err != nil {
logrus.Warnf("Failed to check for setgid on %s: %v", path, err)
} else {
if !isSetgid {
logrus.Warnf("%s should be setgid or have filecaps setgid", path)
}
}
logrus.Warnf("Falling back to single mapping")
g.Reset()
g.Write([]byte(fmt.Sprintf("0 %d 1\n", os.Getegid())))
@@ -262,17 +296,29 @@ func (c *Cmd) Start() error {
fmt.Fprintf(u, "%d %d %d\n", m.ContainerID, m.HostID, m.Size)
}
uidmapSet := false
// Set the GID map.
// Set the UID map.
if c.UseNewuidmap {
cmd := exec.Command("newuidmap", append([]string{pidString}, strings.Fields(strings.Replace(u.String(), "\n", " ", -1))...)...)
path, err := exec.LookPath("newuidmap")
if err != nil {
return errors.Wrapf(err, "error finding newuidmap")
}
cmd := exec.Command(path, append([]string{pidString}, strings.Fields(strings.Replace(u.String(), "\n", " ", -1))...)...)
u.Reset()
cmd.Stdout = u
cmd.Stderr = u
err := cmd.Run()
if err == nil {
if err := cmd.Run(); err == nil {
uidmapSet = true
} else {
logrus.Warnf("Error running newuidmap: %v: %s", err, u.String())
isSetuid, err := IsSetID(path, os.ModeSetuid, capability.CAP_SETUID)
if err != nil {
logrus.Warnf("Failed to check for setuid on %s: %v", path, err)
} else {
if !isSetuid {
logrus.Warnf("%s should be setuid or have filecaps setuid", path)
}
}
logrus.Warnf("Falling back to single mapping")
u.Reset()
u.Write([]byte(fmt.Sprintf("0 %d 1\n", os.Geteuid())))