mirror of
https://github.com/containers/podman.git
synced 2025-11-28 00:59:30 +08:00
Merge pull request #27413 from 0xDVC/fix-26848-userns-pod-validation
Fix user namespace validation for containers in pods
This commit is contained in:
@@ -308,10 +308,6 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
|
|||||||
if c.Flag("cgroups").Changed && vals.CgroupsMode == "split" && registry.IsRemote() {
|
if c.Flag("cgroups").Changed && vals.CgroupsMode == "split" && registry.IsRemote() {
|
||||||
return vals, fmt.Errorf("the option --cgroups=%q is not supported in remote mode", vals.CgroupsMode)
|
return vals, fmt.Errorf("the option --cgroups=%q is not supported in remote mode", vals.CgroupsMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Flag("pod").Changed && !strings.HasPrefix(c.Flag("pod").Value.String(), "new:") && c.Flag("userns").Changed {
|
|
||||||
return vals, errors.New("--userns and --pod cannot be set together")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if c.Flag("shm-size").Changed {
|
if c.Flag("shm-size").Changed {
|
||||||
vals.ShmSize = c.Flag("shm-size").Value.String()
|
vals.ShmSize = c.Flag("shm-size").Value.String()
|
||||||
|
|||||||
@@ -21,6 +21,23 @@ import (
|
|||||||
|
|
||||||
const host = "host"
|
const host = "host"
|
||||||
|
|
||||||
|
// userNSConflictsWithPod returns an error if the user namespace mode
|
||||||
|
// conflicts with pod namespace sharing requirements.
|
||||||
|
// Containers in a pod must use the same user namespace to avoid ownership and
|
||||||
|
// capability issues with shared resources.
|
||||||
|
func userNSConflictsWithPod(pod *libpod.Pod, mode specgen.NamespaceMode) error {
|
||||||
|
if pod != nil && pod.HasInfraContainer() {
|
||||||
|
// Allow modes that don't create a new user namespace
|
||||||
|
switch mode {
|
||||||
|
case specgen.FromPod, specgen.Default, specgen.Host, specgen.FromContainer:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("cannot set user namespace mode when joining pod with infra container: %w", define.ErrInvalidArg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get the default namespace mode for any given namespace type.
|
// Get the default namespace mode for any given namespace type.
|
||||||
func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod) (specgen.Namespace, error) {
|
func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod) (specgen.Namespace, error) {
|
||||||
// The default for most is private
|
// The default for most is private
|
||||||
@@ -211,7 +228,11 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// User
|
// Validate that user namespace mode is compatible with pod.
|
||||||
|
if err := userNSConflictsWithPod(pod, s.UserNS.NSMode); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
switch s.UserNS.NSMode {
|
switch s.UserNS.NSMode {
|
||||||
case specgen.KeepID:
|
case specgen.KeepID:
|
||||||
opts, err := namespaces.UsernsMode(s.UserNS.String()).GetKeepIDOptions()
|
opts, err := namespaces.UsernsMode(s.UserNS.String()).GetKeepIDOptions()
|
||||||
@@ -247,6 +268,10 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
|
|||||||
return nil, fmt.Errorf("looking up container to share user namespace with: %w", err)
|
return nil, fmt.Errorf("looking up container to share user namespace with: %w", err)
|
||||||
}
|
}
|
||||||
toReturn = append(toReturn, libpod.WithUserNSFrom(userCtr))
|
toReturn = append(toReturn, libpod.WithUserNSFrom(userCtr))
|
||||||
|
case specgen.Private:
|
||||||
|
case specgen.Auto:
|
||||||
|
case specgen.NoMap:
|
||||||
|
case specgen.Path:
|
||||||
}
|
}
|
||||||
|
|
||||||
// This wipes the UserNS settings that get set from the infra container
|
// This wipes the UserNS settings that get set from the infra container
|
||||||
@@ -255,8 +280,6 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
|
|||||||
if s.IDMappings != nil {
|
if s.IDMappings != nil {
|
||||||
if pod == nil {
|
if pod == nil {
|
||||||
toReturn = append(toReturn, libpod.WithIDMappings(*s.IDMappings))
|
toReturn = append(toReturn, libpod.WithIDMappings(*s.IDMappings))
|
||||||
} else if pod.HasInfraContainer() && (len(s.IDMappings.UIDMap) > 0 || len(s.IDMappings.GIDMap) > 0) {
|
|
||||||
return nil, fmt.Errorf("cannot specify a new uid/gid map when entering a pod with an infra container: %w", define.ErrInvalidArg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.User != "" {
|
if s.User != "" {
|
||||||
|
|||||||
@@ -678,12 +678,14 @@ var _ = Describe("Podman create", func() {
|
|||||||
create := podmanTest.Podman([]string{"create", "--uidmap", "0:1000:1000", "--pod", "new:testing123", ALPINE})
|
create := podmanTest.Podman([]string{"create", "--uidmap", "0:1000:1000", "--pod", "new:testing123", ALPINE})
|
||||||
create.WaitWithDefaultTimeout()
|
create.WaitWithDefaultTimeout()
|
||||||
Expect(create).ShouldNot(ExitCleanly())
|
Expect(create).ShouldNot(ExitCleanly())
|
||||||
Expect(create.ErrorToString()).To(ContainSubstring("cannot specify a new uid/gid map when entering a pod with an infra container"))
|
Expect(create.ErrorToString()).To(ContainSubstring("cannot set user namespace mode when joining pod with infra container"))
|
||||||
|
|
||||||
|
podmanTest.PodmanExitCleanly("pod", "rm", "-f", "testing123")
|
||||||
|
|
||||||
create = podmanTest.Podman([]string{"create", "--gidmap", "0:1000:1000", "--pod", "new:testing1234", ALPINE})
|
create = podmanTest.Podman([]string{"create", "--gidmap", "0:1000:1000", "--pod", "new:testing1234", ALPINE})
|
||||||
create.WaitWithDefaultTimeout()
|
create.WaitWithDefaultTimeout()
|
||||||
Expect(create).ShouldNot(ExitCleanly())
|
Expect(create).ShouldNot(ExitCleanly())
|
||||||
Expect(create.ErrorToString()).To(ContainSubstring("cannot specify a new uid/gid map when entering a pod with an infra container"))
|
Expect(create.ErrorToString()).To(ContainSubstring("cannot set user namespace mode when joining pod with infra container"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman create --chrootdirs inspection test", func() {
|
It("podman create --chrootdirs inspection test", func() {
|
||||||
|
|||||||
@@ -803,7 +803,7 @@ ENTRYPOINT ["sleep","99999"]
|
|||||||
// fail if --pod and --userns set together
|
// fail if --pod and --userns set together
|
||||||
session = podmanTest.Podman([]string{"run", "--pod", podName, "--userns", "keep-id", ALPINE, "id", "-u"})
|
session = podmanTest.Podman([]string{"run", "--pod", podName, "--userns", "keep-id", ALPINE, "id", "-u"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(ExitWithError(125, "--userns and --pod cannot be set together"))
|
Expect(session).Should(ExitWithError(125, "cannot set user namespace mode when joining pod with infra container"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman pod create with --userns=keep-id can add users", func() {
|
It("podman pod create with --userns=keep-id can add users", func() {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ load helpers
|
|||||||
create,run | --cpu-period=1 | --cpus=2 | $IMAGE
|
create,run | --cpu-period=1 | --cpus=2 | $IMAGE
|
||||||
create,run | --cpu-quota=1 | --cpus=2 | $IMAGE
|
create,run | --cpu-quota=1 | --cpus=2 | $IMAGE
|
||||||
create,run | --no-hosts | --add-host=foo:1.1.1.1 | $IMAGE
|
create,run | --no-hosts | --add-host=foo:1.1.1.1 | $IMAGE
|
||||||
create,run | --userns=bar | --pod=foo | $IMAGE
|
|
||||||
container cleanup | --all | --exec=foo
|
container cleanup | --all | --exec=foo
|
||||||
container cleanup | --exec=foo | --rmi | foo
|
container cleanup | --exec=foo | --rmi | foo
|
||||||
"
|
"
|
||||||
@@ -48,6 +47,14 @@ container cleanup | --exec=foo | --rmi | foo
|
|||||||
"podman $cmd --platform + --$opt"
|
"podman $cmd --platform + --$opt"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# --userns and --pod have a different error message format
|
||||||
|
podname=p-$(safename)
|
||||||
|
run_podman pod create --name $podname
|
||||||
|
run_podman 125 run --uidmap=0:1000:1000 --pod=$podname $IMAGE true
|
||||||
|
is "$output" "Error: cannot set user namespace mode when joining pod with infra container: invalid argument" \
|
||||||
|
"podman run --uidmap + --pod"
|
||||||
|
run_podman pod rm -f $podname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user