github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/unshare.go (about)

     1  // +build !remoteclient
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/exec"
     9  
    10  	"github.com/containers/libpod/cmd/podman/cliconfig"
    11  	"github.com/containers/libpod/pkg/adapter"
    12  	"github.com/containers/libpod/pkg/rootless"
    13  	"github.com/pkg/errors"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  var (
    18  	unshareDescription = "Runs a command in a modified user namespace."
    19  	_unshareCommand    = &cobra.Command{
    20  		Use:   "unshare [flags] [COMMAND [ARG]]",
    21  		Short: "Run a command in a modified user namespace",
    22  		Long:  unshareDescription,
    23  		RunE: func(cmd *cobra.Command, args []string) error {
    24  			unshareCommand.InputArgs = args
    25  			unshareCommand.GlobalFlags = MainGlobalOpts
    26  			return unshareCmd(&unshareCommand)
    27  		},
    28  		Example: `podman unshare id
    29    podman unshare cat /proc/self/uid_map,
    30    podman unshare podman-script.sh`,
    31  	}
    32  	unshareCommand cliconfig.PodmanCommand
    33  )
    34  
    35  func init() {
    36  	unshareCommand.Command = _unshareCommand
    37  	unshareCommand.SetHelpTemplate(HelpTemplate())
    38  	unshareCommand.SetUsageTemplate(UsageTemplate())
    39  	flags := _unshareCommand.Flags()
    40  	flags.SetInterspersed(false)
    41  }
    42  
    43  func unshareEnv(graphroot, runroot string) []string {
    44  	return append(os.Environ(), "_CONTAINERS_USERNS_CONFIGURED=done",
    45  		fmt.Sprintf("CONTAINERS_GRAPHROOT=%s", graphroot),
    46  		fmt.Sprintf("CONTAINERS_RUNROOT=%s", runroot))
    47  }
    48  
    49  // unshareCmd execs whatever using the ID mappings that we want to use for ourselves
    50  func unshareCmd(c *cliconfig.PodmanCommand) error {
    51  
    52  	if isRootless := rootless.IsRootless(); !isRootless {
    53  		return errors.Errorf("please use unshare with rootless")
    54  	}
    55  	// exec the specified command, if there is one
    56  	if len(c.InputArgs) < 1 {
    57  		// try to exec the shell, if one's set
    58  		shell, shellSet := os.LookupEnv("SHELL")
    59  		if !shellSet {
    60  			return errors.Errorf("no command specified and no $SHELL specified")
    61  		}
    62  		c.InputArgs = []string{shell}
    63  	}
    64  
    65  	runtime, err := adapter.GetRuntime(getContext(), c)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	cmd := exec.Command(c.InputArgs[0], c.InputArgs[1:]...)
    70  	cmd.Env = unshareEnv(runtime.StorageConfig().GraphRoot, runtime.StorageConfig().RunRoot)
    71  	cmd.Stdin = os.Stdin
    72  	cmd.Stdout = os.Stdout
    73  	cmd.Stderr = os.Stderr
    74  	return cmd.Run()
    75  }