diff options
-rw-r--r-- | cmd/podman/commands.go | 1 | ||||
-rw-r--r-- | cmd/podman/unshare.go | 54 | ||||
-rw-r--r-- | commands.md | 165 | ||||
-rw-r--r-- | docs/podman-unshare.1.md | 37 | ||||
-rw-r--r-- | docs/podman.1.md | 105 | ||||
-rw-r--r-- | libpod/networking_linux.go | 4 | ||||
-rw-r--r-- | pkg/varlinkapi/attach.go | 16 | ||||
-rw-r--r-- | pkg/varlinkapi/config.go | 4 | ||||
-rw-r--r-- | pkg/varlinkapi/transfers.go | 35 | ||||
-rw-r--r-- | pkg/varlinkapi/util.go | 15 | ||||
-rw-r--r-- | test/e2e/unshare_test.go | 52 |
11 files changed, 331 insertions, 157 deletions
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index 3a409f503..2ac465b9d 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -20,6 +20,7 @@ func getMainCommands() []*cobra.Command { _refreshCommand, _searchCommand, _statsCommand, + _unshareCommand, } if len(_varlinkCommand.Use) > 0 { diff --git a/cmd/podman/unshare.go b/cmd/podman/unshare.go new file mode 100644 index 000000000..1db647dba --- /dev/null +++ b/cmd/podman/unshare.go @@ -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 +} diff --git a/commands.md b/commands.md index e6c211254..d3ceca9dc 100644 --- a/commands.md +++ b/commands.md @@ -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 | diff --git a/docs/podman-unshare.1.md b/docs/podman-unshare.1.md new file mode 100644 index 000000000..a7f018ce1 --- /dev/null +++ b/docs/podman-unshare.1.md @@ -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)
\ No newline at end of file diff --git a/docs/podman.1.md b/docs/podman.1.md index ef12cf1cc..ff942a3c4 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -128,58 +128,59 @@ 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. | -| [podman-container(1)](podman-container.1.md) | Manage containers. | -| [podman-cp(1)](podman-cp.1.md) | Copy files/folders between a container and the local filesystem. | -| [podman-create(1)](podman-create.1.md) | Create a new container. | -| [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. | -| [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-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. | -| [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | -| [podman-info(1)](podman-info.1.md) | Displays Podman related system information. | -| [podman-init(1)](podman-init.1.md) | Initialize a container | -| [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. | -| [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. | -| [podman-load(1)](podman-load.1.md) | Load an image from a container image archive into container storage. | -| [podman-login(1)](podman-login.1.md) | Login to a container registry. | -| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. | -| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. | -| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. | -| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. | -| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. | -| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. | -| [podman-port(1)](podman-port.1.md) | List port mappings for a container. | -| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. | -| [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | -| [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. | -| [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. | -| [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. | -| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. | -| [podman-run(1)](podman-run.1.md) | Run a command in a new container. | -| [podman-save(1)](podman-save.1.md) | Save an image to a container archive. | -| [podman-search(1)](podman-search.1.md) | Search a registry for an image. | -| [podman-start(1)](podman-start.1.md) | Start one or more containers. | -| [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. | -| [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. | -| [podman-system(1)](podman-system.1.md) | Manage podman. | -| [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | -| [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-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. | -| [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. | +| 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. | +| [podman-container(1)](podman-container.1.md) | Manage containers. | +| [podman-cp(1)](podman-cp.1.md) | Copy files/folders between a container and the local filesystem. | +| [podman-create(1)](podman-create.1.md) | Create a new container. | +| [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. | +| [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-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. | +| [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | +| [podman-info(1)](podman-info.1.md) | Displays Podman related system information. | +| [podman-init(1)](podman-init.1.md) | Initialize a container | +| [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. | +| [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. | +| [podman-load(1)](podman-load.1.md) | Load an image from a container image archive into container storage. | +| [podman-login(1)](podman-login.1.md) | Login to a container registry. | +| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. | +| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. | +| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. | +| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. | +| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. | +| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. | +| [podman-port(1)](podman-port.1.md) | List port mappings for a container. | +| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. | +| [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | +| [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. | +| [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. | +| [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. | +| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. | +| [podman-run(1)](podman-run.1.md) | Run a command in a new container. | +| [podman-save(1)](podman-save.1.md) | Save an image to a container archive. | +| [podman-search(1)](podman-search.1.md) | Search a registry for an image. | +| [podman-start(1)](podman-start.1.md) | Start one or more containers. | +| [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. | +| [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. | +| [podman-system(1)](podman-system.1.md) | Manage podman. | +| [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | +| [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. | +| [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. | ## FILES diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 2450bd6b1..b8a916de3 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -19,6 +19,7 @@ import ( "github.com/containers/libpod/pkg/firewall" "github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/netns" + "github.com/containers/libpod/pkg/rootless" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -100,6 +101,9 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re // Create and configure a new network namespace for a container func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q []*cnitypes.Result, err error) { + if rootless.IsRootless() { + return nil, nil, errors.New("cannot configure a new network namespace in rootless mode, only --network=slirp4netns is supported") + } ctrNS, err := netns.NewNS() if err != nil { return nil, nil, errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID()) diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go index 2234899a5..f292bbbf8 100644 --- a/pkg/varlinkapi/attach.go +++ b/pkg/varlinkapi/attach.go @@ -45,22 +45,24 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st var finalErr error resize := make(chan remotecommand.TerminalSize) errChan := make(chan error) + varlink := VarlinkCall{&call} - if !call.WantsUpgrade() { - return call.ReplyErrorOccurred("client must use upgraded connection to attach") + if err := varlink.RequiresUpgrade(); err != nil { + return varlink.ReplyErrorOccurred(err.Error()) } + ctr, err := i.Runtime.LookupContainer(name) if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return varlink.ReplyErrorOccurred(err.Error()) } state, err := ctr.State() if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return varlink.ReplyErrorOccurred(err.Error()) } if !start && state != libpod.ContainerStateRunning { - return call.ReplyErrorOccurred("container must be running to attach") + return varlink.ReplyErrorOccurred("container must be running to attach") } - call.Reply(nil) + reader, writer, _, pw, streams := setupStreams(call) go func() { @@ -81,7 +83,7 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st quitWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.Quit) _, err = quitWriter.Write([]byte("HANG-UP")) // TODO error handling is not quite right here yet - return call.Writer.Flush() + return varlink.Writer.Flush() } func attach(ctr *libpod.Container, streams *libpod.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error { diff --git a/pkg/varlinkapi/config.go b/pkg/varlinkapi/config.go index e75170547..9952c2be1 100644 --- a/pkg/varlinkapi/config.go +++ b/pkg/varlinkapi/config.go @@ -21,3 +21,7 @@ func New(cli *cliconfig.PodmanCommand, runtime *libpod.Runtime) *iopodman.Varlin lp := LibpodAPI{Cli: cli.Command, Runtime: runtime} return iopodman.VarlinkNew(&lp) } + +type VarlinkCall struct { + *iopodman.VarlinkCall +} diff --git a/pkg/varlinkapi/transfers.go b/pkg/varlinkapi/transfers.go index 96f76bcdc..7b38ec5e6 100644 --- a/pkg/varlinkapi/transfers.go +++ b/pkg/varlinkapi/transfers.go @@ -15,58 +15,61 @@ import ( // SendFile allows a client to send a file to the varlink server func (i *LibpodAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int64) error { - if !call.WantsUpgrade() { - return call.ReplyErrorOccurred("client must use upgraded connection to send files") + varlink := VarlinkCall{&call} + if err := varlink.RequiresUpgrade(); err != nil { + return varlink.ReplyErrorOccurred(err.Error()) } outputFile, err := ioutil.TempFile("", "varlink_send") if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return varlink.ReplyErrorOccurred(err.Error()) } defer outputFile.Close() - if err = call.ReplySendFile(outputFile.Name()); err != nil { - return call.ReplyErrorOccurred(err.Error()) + if err = varlink.ReplySendFile(outputFile.Name()); err != nil { + return varlink.ReplyErrorOccurred(err.Error()) } writer := bufio.NewWriter(outputFile) defer writer.Flush() - reader := call.Call.Reader + reader := varlink.Call.Reader if _, err := io.CopyN(writer, reader, length); err != nil { return err } logrus.Debugf("successfully received %s", outputFile.Name()) // Send an ACK to the client - call.Call.Writer.WriteString(fmt.Sprintf("%s:", outputFile.Name())) - call.Call.Writer.Flush() + varlink.Call.Writer.WriteString(fmt.Sprintf("%s:", outputFile.Name())) + varlink.Call.Writer.Flush() return nil } // ReceiveFile allows the varlink server to send a file to a client func (i *LibpodAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, delete bool) error { - if !call.WantsUpgrade() { - return call.ReplyErrorOccurred("client must use upgraded connection to send files") + varlink := VarlinkCall{&call} + if err := varlink.RequiresUpgrade(); err != nil { + return varlink.ReplyErrorOccurred(err.Error()) } + fs, err := os.Open(filepath) if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return varlink.ReplyErrorOccurred(err.Error()) } fileInfo, err := fs.Stat() if err != nil { - return call.ReplyErrorOccurred(err.Error()) + return varlink.ReplyErrorOccurred(err.Error()) } // Send the file length down to client // Varlink connection upraded - if err = call.ReplyReceiveFile(fileInfo.Size()); err != nil { - return call.ReplyErrorOccurred(err.Error()) + if err = varlink.ReplyReceiveFile(fileInfo.Size()); err != nil { + return varlink.ReplyErrorOccurred(err.Error()) } reader := bufio.NewReader(fs) - _, err = reader.WriteTo(call.Writer) + _, err = reader.WriteTo(varlink.Writer) if err != nil { return err } @@ -75,5 +78,5 @@ func (i *LibpodAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, dele return err } } - return call.Writer.Flush() + return varlink.Writer.Flush() } diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go index 8716c963a..a9f1e20a1 100644 --- a/pkg/varlinkapi/util.go +++ b/pkg/varlinkapi/util.go @@ -13,6 +13,11 @@ import ( "github.com/containers/libpod/cmd/podman/varlink" "github.com/containers/libpod/libpod" "github.com/containers/storage/pkg/archive" + "github.com/pkg/errors" +) + +var ( + ErrUpgradedConnectionRequired = errors.New("peer must use upgraded connection for operation") ) // getContext returns a non-nil, empty context @@ -195,3 +200,13 @@ func makePsOpts(inOpts iopodman.PsOpts) shared.PsOptions { Sync: derefBool(inOpts.Sync), } } + +// RequiresUpgrade tests if varlink connection has been marked for upgrade. +func (v *VarlinkCall) RequiresUpgrade() error { + if v.WantsUpgrade() { + // A nil is sent to the peer as required by the varlink protocol. + return v.Reply(nil) + } else { + return ErrUpgradedConnectionRequired + } +} diff --git a/test/e2e/unshare_test.go b/test/e2e/unshare_test.go new file mode 100644 index 000000000..1e3f06a62 --- /dev/null +++ b/test/e2e/unshare_test.go @@ -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()) + }) +}) |