Add unshare to podman

This command lets the user run a command in a new user namespace like `unshare -u`.
It uses the implementation of unshare in buildah. ( fixes #1388 )

Signed-off-by: Divyansh Kamboj <kambojdivyansh2000@gmail.com>
This commit is contained in:
Divyansh Kamboj
2019-04-21 16:22:50 +05:30
parent 5445d7d104
commit 2a961a7113
6 changed files with 280 additions and 134 deletions

View File

@ -20,6 +20,7 @@ func getMainCommands() []*cobra.Command {
_refreshCommand,
_searchCommand,
_statsCommand,
_unshareCommand,
}
if len(_varlinkCommand.Use) > 0 {

54
cmd/podman/unshare.go Normal file
View File

@ -0,0 +1,54 @@
// +build linux
package main
import (
"os"
"os/exec"
"github.com/containers/buildah/pkg/unshare"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
unshareDescription = "Runs a command in a modified user namespace."
_unshareCommand = &cobra.Command{
Use: "unshare [flags] [COMMAND [ARG]]",
Short: "Run a command in a modified user namespace",
Long: unshareDescription,
RunE: unshareCmd,
Example: `podman unshare id
podman unshare cat /proc/self/uid_map,
podman unshare podman-script.sh`,
}
)
func init() {
_unshareCommand.SetUsageTemplate(UsageTemplate())
flags := _unshareCommand.Flags()
flags.SetInterspersed(false)
}
// unshareCmd execs whatever using the ID mappings that we want to use for ourselves
func unshareCmd(c *cobra.Command, args []string) error {
if isRootless := unshare.IsRootless(); !isRootless {
return errors.Errorf("please use unshare with rootless")
}
// exec the specified command, if there is one
if len(args) < 1 {
// try to exec the shell, if one's set
shell, shellSet := os.LookupEnv("SHELL")
if !shellSet {
return errors.Errorf("no command specified and no $SHELL specified")
}
args = []string{shell}
}
cmd := exec.Command(args[0], args[1:]...)
cmd.Env = unshare.RootlessEnv()
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
unshare.ExecRunnable(cmd)
return nil
}

View File

@ -4,85 +4,86 @@
## Podman Commands
Command | Description | Demo | Script
:----------------------------------------------------------------------- | :------------------------------------------------------------------------- | :-------------------------------------------------------------------------- | :--------------------------------------------------------------------------
[podman(1)](/docs/podman.1.md) | Simple management tool for pods and images |
[podman-attach(1)](/docs/podman-attach.1.md) | Attach to a running container |
[podman-build(1)](/docs/podman-build.1.md) | Build an image using instructions from Dockerfiles |
[podman-commit(1)](/docs/podman-commit.1.md) | Create new image based on the changed container |
[podman-container(1)](/docs/podman-container.1.md) | Manage Containers |
[podman-container-checkpoint(1)](/docs/podman-container-checkpoint.1.md) | Checkpoints one or more running containers |
[podman-container-cleanup(1)](/docs/podman-container-cleanup.1.md) | Cleanup Container storage and networks |
[podman-container-exists(1)](/docs/podman-container-exists.1.md) | Check if an container exists in local storage |
[podman-container-prune(1)](/docs/podman-container-prune.1.md) | Remove all stopped containers |
[podman-container-refresh(1)](/docs/podman-container-refresh.1.md) | Refresh all containers state in database |
[podman-container-restore(1)](/docs/podman-container-restore.1.md) | Restores one or more running containers |
[podman-container-runlabel(1)](/docs/podman-container-runlabel.1.md) | Execute Image Label Method |
[podman-cp(1)](/docs/podman-cp.1.md) | Copy files/folders between a container and the local filesystem |
[podman-create(1)](/docs/podman-create.1.md) | Create a new container |
[podman-diff(1)](/docs/podman-diff.1.md) | Inspect changes on a container or image's filesystem |
[podman-events(1)](/docs/podman-events.1.md) | Monitor Podman events |
[podman-exec(1)](/docs/podman-exec.1.md) | Execute a command in a running container |
[podman-export(1)](/docs/podman-export.1.md) | Export container's filesystem contents as a tar archive |
[podman-generate(1)](/docs/podman-generate.1.md) | Generate structured output based on Podman containers and pods |
[podman-generate-kube(1)](/docs/podman-generate-kube.1.md) | Generate Kubernetes YAML based on a container or Pod |
[podman-generate-systemd(1)](/docs/podman-generate-systemd.1.md) | Generate a Systemd unit file for a container |
[podman-history(1)](/docs/podman-history.1.md) | Shows the history of an image |
[podman-image(1)](/docs/podman-image.1.md) | Manage Images |
[podman-image-exists(1)](/docs/podman-image-exists.1.md) | Check if an image exists in local storage |
[podman-image-prune(1)](/docs/podman-image-prune.1.md) | Remove all unused images |
[podman-image-sign(1)](/docs/podman-image-sign.1.md) | Create a signature for an image |
[podman-image-trust(1)](/docs/podman-image-trust.1.md) | Manage container registry image trust policy |
[podman-images(1)](/docs/podman-images.1.md) | List images in local storage | [![...](/docs/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh)
[podman-import(1)](/docs/podman-import.1.md) | Import a tarball and save it as a filesystem image |
[podman-info(1)](/docs/podman-info.1.md) | Display system information |
[podman-init(1)](/docs/podman-init.1.md) | Initialize a container |
[podman-inspect(1)](/docs/podman-inspect.1.md) | Display the configuration of a container or image | [![...](/docs/play.png)](https://asciinema.org/a/133418)
[podman-kill(1)](/docs/podman-kill.1.md) | Kill the main process in one or more running containers |
[podman-load(1)](/docs/podman-load.1.md) | Load an image from a container image archive |
[podman-login(1)](/docs/podman-login.1.md) | Login to a container registry |
[podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
[podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
[podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
[podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292)
[podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
[podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
[podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod |
[podman-pod-inspect(1)](/docs/podman-pod-inspect.1.md) | Inspect a pod |
[podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
[podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system |
[podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
[podman-pod-restart](/docs/podman-pod-restart.1.md) | Restart one or more pods |
[podman-pod-rm(1)](/docs/podman-pod-rm.1.md) | Remove one or more pods |
[podman-pod-start(1)](/docs/podman-pod-start.1.md) | Start one or more pods |
[podman-pod-stats(1)](/docs/podman-pod-stats.1.md) | Display a live stream of one or more pods' resource usage statistics | | |
[podman-pod-stop(1)](/docs/podman-pod-stop.1.md) | Stop one or more pods |
[podman-pod-top(1)](/docs/podman-pod-top.1.md) | Display the running processes of a pod |
[podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
[podman-port(1)](/docs/podman-port.1.md) | List port mappings for running containers |
[podman-ps(1)](/docs/podman-ps.1.md) | Prints out information about containers |
[podman-pull(1)](/docs/podman-pull.1.md) | Pull an image from a registry |
[podman-push(1)](/docs/podman-push.1.md) | Push an image to a specified destination | [![...](/docs/play.png)](https://asciinema.org/a/133276)
[podman-restart](/docs/podman-restart.1.md) | Restarts one or more containers | [![...](/docs/play.png)](https://asciinema.org/a/jiqxJAxcVXw604xdzMLTkQvHM)
[podman-rm(1)](/docs/podman-rm.1.md) | Removes one or more containers |
[podman-rmi(1)](/docs/podman-rmi.1.md) | Removes one or more images |
[podman-run(1)](/docs/podman-run.1.md) | Run a command in a container |
[podman-save(1)](/docs/podman-save.1.md) | Saves an image to an archive |
[podman-search(1)](/docs/podman-search.1.md) | Search a registry for an image |
[podman-start(1)](/docs/podman-start.1.md) | Starts one or more containers |
[podman-stats(1)](/docs/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
[podman-stop(1)](/docs/podman-stop.1.md) | Stops one or more running containers |
[podman-system(1)](/docs/podman-system.1.md) | Manage podman |
[podman-tag(1)](/docs/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/play.png)](https://asciinema.org/a/133803)
[podman-top(1)](/docs/podman-top.1.md) | Display the running processes of a container |
[podman-umount(1)](/docs/podman-umount.1.md) | Unmount a working container's root filesystem |
[podman-unpause(1)](/docs/podman-unpause.1.md) | Unpause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292)
[podman-varlink(1)](/docs/podman-varlink.1.md) | Run the varlink backend |
[podman-version(1)](/docs/podman-version.1.md) | Display the version information |
[podman-volume(1)](/docs/podman-volume.1.md) | Manage Volumes |
[podman-volume-create(1)](/docs/podman-volume-create.1.md) | Create a volume |
[podman-volume-inspect(1)](/docs/podman-volume-inspect.1.md) | Get detailed information on one or more volumes |
[podman-volume-ls(1)](/docs/podman-volume-ls.1.md) | List all the available volumes |
[podman-volume-rm(1)](/docs/podman-volume-rm.1.md) | Remove one or more volumes |
[podman-volume-prune(1)](/docs/podman-volume-prune.1.md) | Remove all unused volumes |
[podman-wait(1)](/docs/podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes
| Command | Description | Demo | Script |
| :----------------------------------------------------------------------- | :------------------------------------------------------------------------- | :-------------------------------------------------------------------------- | :---------------------------------------------------------------------------------- |
| [podman(1)](/docs/podman.1.md) | Simple management tool for pods and images |
| [podman-attach(1)](/docs/podman-attach.1.md) | Attach to a running container |
| [podman-build(1)](/docs/podman-build.1.md) | Build an image using instructions from Dockerfiles |
| [podman-commit(1)](/docs/podman-commit.1.md) | Create new image based on the changed container |
| [podman-container(1)](/docs/podman-container.1.md) | Manage Containers |
| [podman-container-checkpoint(1)](/docs/podman-container-checkpoint.1.md) | Checkpoints one or more running containers |
| [podman-container-cleanup(1)](/docs/podman-container-cleanup.1.md) | Cleanup Container storage and networks |
| [podman-container-exists(1)](/docs/podman-container-exists.1.md) | Check if an container exists in local storage |
| [podman-container-prune(1)](/docs/podman-container-prune.1.md) | Remove all stopped containers |
| [podman-container-refresh(1)](/docs/podman-container-refresh.1.md) | Refresh all containers state in database |
| [podman-container-restore(1)](/docs/podman-container-restore.1.md) | Restores one or more running containers |
| [podman-container-runlabel(1)](/docs/podman-container-runlabel.1.md) | Execute Image Label Method |
| [podman-cp(1)](/docs/podman-cp.1.md) | Copy files/folders between a container and the local filesystem |
| [podman-create(1)](/docs/podman-create.1.md) | Create a new container |
| [podman-diff(1)](/docs/podman-diff.1.md) | Inspect changes on a container or image's filesystem |
| [podman-events(1)](/docs/podman-events.1.md) | Monitor Podman events |
| [podman-exec(1)](/docs/podman-exec.1.md) | Execute a command in a running container |
| [podman-export(1)](/docs/podman-export.1.md) | Export container's filesystem contents as a tar archive |
| [podman-generate(1)](/docs/podman-generate.1.md) | Generate structured output based on Podman containers and pods |
| [podman-generate-kube(1)](/docs/podman-generate-kube.1.md) | Generate Kubernetes YAML based on a container or Pod |
| [podman-generate-systemd(1)](/docs/podman-generate-systemd.1.md) | Generate a Systemd unit file for a container |
| [podman-history(1)](/docs/podman-history.1.md) | Shows the history of an image |
| [podman-image(1)](/docs/podman-image.1.md) | Manage Images |
| [podman-image-exists(1)](/docs/podman-image-exists.1.md) | Check if an image exists in local storage |
| [podman-image-prune(1)](/docs/podman-image-prune.1.md) | Remove all unused images |
| [podman-image-sign(1)](/docs/podman-image-sign.1.md) | Create a signature for an image |
| [podman-image-trust(1)](/docs/podman-image-trust.1.md) | Manage container registry image trust policy |
| [podman-images(1)](/docs/podman-images.1.md) | List images in local storage | [![...](/docs/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh) |
| [podman-import(1)](/docs/podman-import.1.md) | Import a tarball and save it as a filesystem image |
| [podman-info(1)](/docs/podman-info.1.md) | Display system information |
| [podman-init(1)](/docs/podman-init.1.md) | Initialize a container |
| [podman-inspect(1)](/docs/podman-inspect.1.md) | Display the configuration of a container or image | [![...](/docs/play.png)](https://asciinema.org/a/133418) |
| [podman-kill(1)](/docs/podman-kill.1.md) | Kill the main process in one or more running containers |
| [podman-load(1)](/docs/podman-load.1.md) | Load an image from a container image archive |
| [podman-login(1)](/docs/podman-login.1.md) | Login to a container registry |
| [podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292) |
| [podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
| [podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod |
| [podman-pod-inspect(1)](/docs/podman-pod-inspect.1.md) | Inspect a pod |
| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
| [podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system |
| [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
| [podman-pod-restart](/docs/podman-pod-restart.1.md) | Restart one or more pods |
| [podman-pod-rm(1)](/docs/podman-pod-rm.1.md) | Remove one or more pods |
| [podman-pod-start(1)](/docs/podman-pod-start.1.md) | Start one or more pods |
| [podman-pod-stats(1)](/docs/podman-pod-stats.1.md) | Display a live stream of one or more pods' resource usage statistics | | |
| [podman-pod-stop(1)](/docs/podman-pod-stop.1.md) | Stop one or more pods |
| [podman-pod-top(1)](/docs/podman-pod-top.1.md) | Display the running processes of a pod |
| [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
| [podman-port(1)](/docs/podman-port.1.md) | List port mappings for running containers |
| [podman-ps(1)](/docs/podman-ps.1.md) | Prints out information about containers |
| [podman-pull(1)](/docs/podman-pull.1.md) | Pull an image from a registry |
| [podman-push(1)](/docs/podman-push.1.md) | Push an image to a specified destination | [![...](/docs/play.png)](https://asciinema.org/a/133276) |
| [podman-restart](/docs/podman-restart.1.md) | Restarts one or more containers | [![...](/docs/play.png)](https://asciinema.org/a/jiqxJAxcVXw604xdzMLTkQvHM) |
| [podman-rm(1)](/docs/podman-rm.1.md) | Removes one or more containers |
| [podman-rmi(1)](/docs/podman-rmi.1.md) | Removes one or more images |
| [podman-run(1)](/docs/podman-run.1.md) | Run a command in a container |
| [podman-save(1)](/docs/podman-save.1.md) | Saves an image to an archive |
| [podman-search(1)](/docs/podman-search.1.md) | Search a registry for an image |
| [podman-start(1)](/docs/podman-start.1.md) | Starts one or more containers |
| [podman-stats(1)](/docs/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
| [podman-stop(1)](/docs/podman-stop.1.md) | Stops one or more running containers |
| [podman-system(1)](/docs/podman-system.1.md) | Manage podman |
| [podman-tag(1)](/docs/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/play.png)](https://asciinema.org/a/133803) |
| [podman-top(1)](/docs/podman-top.1.md) | Display the running processes of a container |
| [podman-umount(1)](/docs/podman-umount.1.md) | Unmount a working container's root filesystem |
| [podman-unpause(1)](/docs/podman-unpause.1.md) | Unpause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292) |
| [podman-unshare(1)](/docs/podman-unshare.1.md) | Run a command inside of a modified user namespace. |
| [podman-varlink(1)](/docs/podman-varlink.1.md) | Run the varlink backend |
| [podman-version(1)](/docs/podman-version.1.md) | Display the version information |
| [podman-volume(1)](/docs/podman-volume.1.md) | Manage Volumes |
| [podman-volume-create(1)](/docs/podman-volume-create.1.md) | Create a volume |
| [podman-volume-inspect(1)](/docs/podman-volume-inspect.1.md) | Get detailed information on one or more volumes |
| [podman-volume-ls(1)](/docs/podman-volume-ls.1.md) | List all the available volumes |
| [podman-volume-rm(1)](/docs/podman-volume-rm.1.md) | Remove one or more volumes |
| [podman-volume-prune(1)](/docs/podman-volume-prune.1.md) | Remove all unused volumes |
| [podman-wait(1)](/docs/podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes |

37
docs/podman-unshare.1.md Normal file
View File

@ -0,0 +1,37 @@
% podman-unshare "1"
## NAME
podman\-unshare - Run a command inside of a modified user namespace.
## SYNOPSIS
**podman unshare** [*options*] [**--**] [*command*]
## DESCRIPTION
Launches a process (by default, *$SHELL*) in a new user namespace. The user
namespace is configured so that the invoking user's UID and primary GID appear
to be UID 0 and GID 0, respectively. Any ranges which match that user and
group in /etc/subuid and /etc/subgid are also mapped in as themselves with the
help of the *newuidmap(1)* and *newgidmap(1)* helpers.
podman unshare is useful for troubleshooting unprivileged operations and for
manually clearing storage and other data related to images and containers.
It is also useful if you want to use the `podman mount` command. If an unprivileged users wants to mount and work with a container, then they need to execute
podman unshare. Executing `podman mount` fails for unprivileged users unless the user is running inside a `podman unshare` session.
## EXAMPLE
```
$ podman unshare id
uid=0(root) gid=0(root) groups=0(root),65534(nobody)
$ podman unshare cat /proc/self/uid_map /proc/self/gid_map
0 1000 1
1 10000 65536
0 1000 1
1 10000 65536
```
## SEE ALSO
podman(1), podman-mount(1), namespaces(7), newuidmap(1), newgidmap(1), user\_namespaces(7)

View File

@ -129,7 +129,7 @@ the exit codes follow the `chroot` standard, see below:
## COMMANDS
| Command | Description |
| ----------------------------------------- | ------------------------------------------------------------------------------ |
| ------------------------------------------------ | --------------------------------------------------------------------------- |
| [podman-attach(1)](podman-attach.1.md) | Attach to a running container. |
| [podman-build(1)](podman-build.1.md) | Build a container image using a Dockerfile. |
| [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. |
@ -140,8 +140,8 @@ the exit codes follow the `chroot` standard, see below:
| [podman-events(1)](podman-events.1.md) | Monitor Podman events |
| [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. |
| [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
| [podman-generate(1)](podman-generate.1.md)| Generate structured data based for a containers and pods. |
| [podman-healthcheck(1)](podman-healthcheck.1.md)| Manage healthchecks for containers |
| [podman-generate(1)](podman-generate.1.md) | Generate structured data based for a containers and pods. |
| [podman-healthcheck(1)](podman-healthcheck.1.md) | Manage healthchecks for containers |
| [podman-history(1)](podman-history.1.md) | Show the history of an image. |
| [podman-image(1)](podman-image.1.md) | Manage images. |
| [podman-images(1)](podman-images.1.md) | List images in local storage. |
@ -176,6 +176,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-top(1)](podman-top.1.md) | Display the running processes of a container. |
| [podman-umount(1)](podman-umount.1.md) | Unmount a working container's root filesystem. |
| [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. |
| [podman-unshare(1)](podman-unshare.1.md) | Run a command inside of a modified user namespace. |
| [podman-version(1)](podman-varlink.1.md) | Runs the varlink backend interface. |
| [podman-varlink(1)](podman-version.1.md) | Display the Podman version information. |
| [podman-volume(1)](podman-volume.1.md) | Manage Volumes. |

52
test/e2e/unshare_test.go Normal file
View File

@ -0,0 +1,52 @@
package integration
import (
"os"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Podman unshare", func() {
var (
tempdir string
err error
podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
SkipIfRemote()
if _, err := os.Stat("/proc/self/uid_map"); err != nil {
Skip("User namespaces not supported.")
}
if os.Geteuid() == 0 {
Skip("Use unshare in rootless only")
}
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
}
podmanTest = PodmanTestCreate(tempdir)
podmanTest.CgroupManager = "cgroupfs"
podmanTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS
podmanTest.Setup()
podmanTest.RestoreAllArtifacts()
})
AfterEach(func() {
podmanTest.Cleanup()
f := CurrentGinkgoTestDescription()
processTestResult(f)
})
It("podman unshare", func() {
userNS, _ := os.Readlink("/proc/self/ns/user")
session := podmanTest.Podman([]string{"unshare", "readlink", "/proc/self/ns/user"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ok, _ := session.GrepString(userNS)
Expect(ok).To(BeFalse())
})
})