mirror of
https://github.com/containers/podman.git
synced 2025-10-17 19:24:04 +08:00
podman: implement userns=keep-id
add missing implementation for userns=keep-id and enable the user namespaces tests. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
@ -246,20 +246,6 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
|
||||
s.NetNS = c.Net.Network
|
||||
}
|
||||
|
||||
// TODO this is going to have to be done the libpod/server end of things
|
||||
// USER
|
||||
//user := c.String("user")
|
||||
//if user == "" {
|
||||
// switch {
|
||||
// case usernsMode.IsKeepID():
|
||||
// user = fmt.Sprintf("%d:%d", rootless.GetRootlessUID(), rootless.GetRootlessGID())
|
||||
// case data == nil:
|
||||
// user = "0"
|
||||
// default:
|
||||
// user = data.Config.User
|
||||
// }
|
||||
//}
|
||||
|
||||
// STOP SIGNAL
|
||||
signalString := "TERM"
|
||||
if sig := c.StopSignal; len(sig) > 0 {
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/containers/libpod/pkg/cgroups"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/containers/libpod/pkg/specgen"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/pkg/errors"
|
||||
@ -175,6 +176,13 @@ func GenerateNamespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod
|
||||
|
||||
// User
|
||||
switch s.UserNS.NSMode {
|
||||
case specgen.KeepID:
|
||||
if rootless.IsRootless() {
|
||||
s.User = ""
|
||||
} else {
|
||||
// keep-id as root doesn't need a user namespace
|
||||
s.UserNS.NSMode = specgen.Host
|
||||
}
|
||||
case specgen.FromPod:
|
||||
if pod == nil || infraCtr == nil {
|
||||
return nil, errNoInfra
|
||||
@ -378,6 +386,18 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt
|
||||
if err := g.RemoveLinuxNamespace(string(spec.UserNamespace)); err != nil {
|
||||
return err
|
||||
}
|
||||
case specgen.KeepID:
|
||||
var (
|
||||
err error
|
||||
uid, gid int
|
||||
)
|
||||
s.IDMappings, uid, gid, err = util.GetKeepIDMapping()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.SetProcessUID(uint32(uid))
|
||||
g.SetProcessGID(uint32(gid))
|
||||
fallthrough
|
||||
case specgen.Private:
|
||||
if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
|
||||
return err
|
||||
|
@ -76,6 +76,17 @@ func (n *Namespace) IsPod() bool {
|
||||
func (n *Namespace) IsPrivate() bool {
|
||||
return n.NSMode == Private
|
||||
}
|
||||
|
||||
// IsAuto indicates the namespace is auto
|
||||
func (n *Namespace) IsAuto() bool {
|
||||
return n.NSMode == Auto
|
||||
}
|
||||
|
||||
// IsKeepID indicates the namespace is KeepID
|
||||
func (n *Namespace) IsKeepID() bool {
|
||||
return n.NSMode == KeepID
|
||||
}
|
||||
|
||||
func validateUserNS(n *Namespace) error {
|
||||
if n == nil {
|
||||
return nil
|
||||
@ -186,12 +197,11 @@ func ParseUserNamespace(ns string) (Namespace, error) {
|
||||
if len(split) != 2 {
|
||||
return toReturn, errors.Errorf("invalid setting for auto: mode")
|
||||
}
|
||||
toReturn.NSMode = KeepID
|
||||
toReturn.NSMode = Auto
|
||||
toReturn.Value = split[1]
|
||||
return toReturn, nil
|
||||
case ns == "keep-id":
|
||||
toReturn.NSMode = KeepID
|
||||
toReturn.NSMode = FromContainer
|
||||
return toReturn, nil
|
||||
}
|
||||
return ParseNamespace(ns)
|
||||
|
@ -330,6 +330,58 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// GetKeepIDMapping returns the mappings and the user to use when keep-id is used
|
||||
func GetKeepIDMapping() (*storage.IDMappingOptions, int, int, error) {
|
||||
options := storage.IDMappingOptions{
|
||||
HostUIDMapping: true,
|
||||
HostGIDMapping: true,
|
||||
}
|
||||
uid, gid := 0, 0
|
||||
if rootless.IsRootless() {
|
||||
min := func(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
uid = rootless.GetRootlessUID()
|
||||
gid = rootless.GetRootlessGID()
|
||||
|
||||
uids, gids, err := rootless.GetConfiguredMappings()
|
||||
if err != nil {
|
||||
return nil, -1, -1, errors.Wrapf(err, "cannot read mappings")
|
||||
}
|
||||
maxUID, maxGID := 0, 0
|
||||
for _, u := range uids {
|
||||
maxUID += u.Size
|
||||
}
|
||||
for _, g := range gids {
|
||||
maxGID += g.Size
|
||||
}
|
||||
|
||||
options.UIDMap, options.GIDMap = nil, nil
|
||||
|
||||
options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(uid, maxUID)})
|
||||
options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1})
|
||||
if maxUID > uid {
|
||||
options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid})
|
||||
}
|
||||
|
||||
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(gid, maxGID)})
|
||||
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1})
|
||||
if maxGID > gid {
|
||||
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
|
||||
}
|
||||
|
||||
options.HostUIDMapping = false
|
||||
options.HostGIDMapping = false
|
||||
|
||||
}
|
||||
// Simply ignore the setting and do not setup an inner namespace for root as it is a no-op
|
||||
return &options, uid, gid, nil
|
||||
}
|
||||
|
||||
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
|
||||
func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) {
|
||||
options := storage.IDMappingOptions{
|
||||
@ -350,53 +402,8 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin
|
||||
return &options, nil
|
||||
}
|
||||
if mode.IsKeepID() {
|
||||
if len(uidMapSlice) > 0 || len(gidMapSlice) > 0 {
|
||||
return nil, errors.New("cannot specify custom mappings with --userns=keep-id")
|
||||
}
|
||||
if len(subUIDMap) > 0 || len(subGIDMap) > 0 {
|
||||
return nil, errors.New("cannot specify subuidmap or subgidmap with --userns=keep-id")
|
||||
}
|
||||
if rootless.IsRootless() {
|
||||
min := func(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
uid := rootless.GetRootlessUID()
|
||||
gid := rootless.GetRootlessGID()
|
||||
|
||||
uids, gids, err := rootless.GetConfiguredMappings()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot read mappings")
|
||||
}
|
||||
maxUID, maxGID := 0, 0
|
||||
for _, u := range uids {
|
||||
maxUID += u.Size
|
||||
}
|
||||
for _, g := range gids {
|
||||
maxGID += g.Size
|
||||
}
|
||||
|
||||
options.UIDMap, options.GIDMap = nil, nil
|
||||
|
||||
options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(uid, maxUID)})
|
||||
options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1})
|
||||
if maxUID > uid {
|
||||
options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid})
|
||||
}
|
||||
|
||||
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(gid, maxGID)})
|
||||
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1})
|
||||
if maxGID > gid {
|
||||
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
|
||||
}
|
||||
|
||||
options.HostUIDMapping = false
|
||||
options.HostGIDMapping = false
|
||||
}
|
||||
// Simply ignore the setting and do not setup an inner namespace for root as it is a no-op
|
||||
options.HostUIDMapping = false
|
||||
options.HostGIDMapping = false
|
||||
return &options, nil
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ var _ = Describe("Podman UserNS support", func() {
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
Skip(v2fail)
|
||||
if os.Getenv("SKIP_USERNS") != "" {
|
||||
Skip("Skip userns tests.")
|
||||
}
|
||||
@ -219,6 +218,7 @@ var _ = Describe("Podman UserNS support", func() {
|
||||
})
|
||||
|
||||
It("podman --userns=container:CTR", func() {
|
||||
Skip(v2fail)
|
||||
ctrName := "userns-ctr"
|
||||
session := podmanTest.Podman([]string{"run", "-d", "--uidmap=0:0:1", "--uidmap=1:1:4998", "--name", ctrName, "alpine", "top"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
|
Reference in New Issue
Block a user