Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libpod: allow userns=keep-id for root #17350

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/source/markdown/options/userns.container.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Example: `containers:2147483647:2147483648`.

Podman allocates unique ranges of UIDs and GIDs from the `containers` subordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option.

The rootless option `--userns=keep-id` uses all the subuids and subgids of the user. Using `--userns=auto` when starting new containers will not work as long as any containers exist that were started with `--userns=keep-id`.
The option `--userns=keep-id` uses all the subuids and subgids of the user. Using `--userns=auto` when starting new containers will not work as long as any containers exist that were started with `--userns=keep-id`.

Valid `auto` options:

Expand All @@ -40,12 +40,12 @@ The rootless option `--userns=keep-id` uses all the subuids and subgids of the u

**host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).

**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user.
**keep-id**: creates a user namespace where the current user's UID:GID are mapped to the same values in the container. For containers created by root, the current mapping is created into a new user namespace.

Valid `keep-id` options:

- *uid*=UID: override the UID inside the container that will be used to map the current rootless user to.
- *gid*=GID: override the GID inside the container that will be used to map the current rootless user to.
- *uid*=UID: override the UID inside the container that will be used to map the current user to.
- *gid*=GID: override the GID inside the container that will be used to map the current user to.

**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user.

Expand Down
4 changes: 0 additions & 4 deletions pkg/specgen/generate/namespaces.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package generate

import (
"errors"
"fmt"
"strings"

Expand Down Expand Up @@ -194,9 +193,6 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.
// User
switch s.UserNS.NSMode {
case specgen.KeepID:
if !rootless.IsRootless() {
return nil, errors.New("keep-id is only supported in rootless mode")
}
opts, err := namespaces.UsernsMode(s.UserNS.String()).GetKeepIDOptions()
if err != nil {
return nil, err
Expand Down
27 changes: 24 additions & 3 deletions pkg/util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,34 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {

// GetKeepIDMapping returns the mappings and the user to use when keep-id is used
func GetKeepIDMapping(opts *namespaces.KeepIDUserNsOptions) (*stypes.IDMappingOptions, int, int, error) {
if !rootless.IsRootless() {
return nil, -1, -1, errors.New("keep-id is only supported in rootless mode")
}
options := stypes.IDMappingOptions{
HostUIDMapping: false,
HostGIDMapping: false,
}

if !rootless.IsRootless() {
uids, err := rootless.ReadMappingsProc("/proc/self/uid_map")
if err != nil {
return nil, 0, 0, err
}
gids, err := rootless.ReadMappingsProc("/proc/self/uid_map")
if err != nil {
return nil, 0, 0, err
}
options.UIDMap = uids
options.GIDMap = gids

uid, gid := 0, 0
if opts.UID != nil {
uid = int(*opts.UID)
}
if opts.GID != nil {
gid = int(*opts.GID)
}

return &options, uid, gid, nil
}

min := func(a, b int) int {
if a < b {
return a
Expand Down
16 changes: 0 additions & 16 deletions test/e2e/run_userns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,30 +128,19 @@ var _ = Describe("Podman UserNS support", func() {
It("podman --userns=keep-id", func() {
session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "id", "-u"})
session.WaitWithDefaultTimeout()
if !isRootless() {
Expect(session).Should(Exit(125))
Expect(session.ErrorToString()).To(ContainSubstring("keep-id is only supported in rootless mode"))
return
}

Expect(session).Should(Exit(0))
uid := fmt.Sprintf("%d", os.Geteuid())
Expect(session.OutputToString()).To(ContainSubstring(uid))

session = podmanTest.Podman([]string{"run", "--userns=keep-id:uid=10,gid=12", "alpine", "sh", "-c", "echo $(id -u):$(id -g)"})
session.WaitWithDefaultTimeout()
if !isRootless() {
Expect(session).Should(Exit(125))
Expect(session.ErrorToString()).To(ContainSubstring("keep-id is only supported in rootless mode"))
return
}

Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("10:12"))
})

It("podman --userns=keep-id check passwd", func() {
SkipIfNotRootless("keep-id only works in rootless mode")
session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "id", "-un"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expand All @@ -161,23 +150,20 @@ var _ = Describe("Podman UserNS support", func() {
})

It("podman --userns=keep-id root owns /usr", func() {
SkipIfNotRootless("keep-id only works in rootless mode")
session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "stat", "-c%u", "/usr"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Equal("0"))
})

It("podman --userns=keep-id --user root:root", func() {
SkipIfNotRootless("keep-id only works in rootless mode")
session := podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", "alpine", "id", "-u"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Equal("0"))
})

It("podman run --userns=keep-id can add users", func() {
SkipIfNotRootless("keep-id only works in rootless mode")
userName := os.Getenv("USER")
if userName == "" {
Skip("Can't complete test if no username available")
Expand Down Expand Up @@ -403,8 +389,6 @@ var _ = Describe("Podman UserNS support", func() {
})

It("podman PODMAN_USERNS", func() {
SkipIfNotRootless("keep-id only works in rootless mode")

podmanUserns, podmanUserusSet := os.LookupEnv("PODMAN_USERNS")
os.Setenv("PODMAN_USERNS", "keep-id")
defer func() {
Expand Down
26 changes: 8 additions & 18 deletions test/system/170-run-userns.bats
Original file line number Diff line number Diff line change
Expand Up @@ -131,25 +131,15 @@ EOF
}

@test "podman userns=keep-id" {
if is_rootless; then
user=$(id -u)
run_podman run --rm --userns=keep-id $IMAGE id -u
is "${output}" "$user" "Container should run as the current user"
else
run_podman 125 run --rm --userns=keep-id $IMAGE id -u
is "${output}" "Error: keep-id is only supported in rootless mode" "Container should fail to start since keep-id is not supported in rootful mode"
fi
user=$(id -u)
run_podman run --rm --userns=keep-id $IMAGE id -u
is "${output}" "$user" "Container should run as the current user"
}

@test "podman userns=keep-id in a pod" {
if is_rootless; then
user=$(id -u)
run_podman pod create --userns keep-id
pid=$output
run_podman run --rm --pod $pid $IMAGE id -u
is "${output}" "$user" "Container should run as the current user"
else
run_podman 125 pod create --userns keep-id
is "${output}" 'Error:.*keep-id is only supported in rootless mode' "pod should fail to be created since keep-id is not supported in rootful mode"
fi
user=$(id -u)
run_podman pod create --userns keep-id
pid=$output
run_podman run --rm --pod $pid $IMAGE id -u
is "${output}" "$user" "Container should run as the current user"
}