github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/cmds/unshare/unshare.go (about)

     1  // Copyright 2016-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Disassociate parts of the process execution context.
     6  //
     7  // Synopsis:
     8  //     unshare [OPTIONS] [PROGRAM [ARGS]...]
     9  //
    10  // Description:
    11  //     Go applications use multiple processes, and the Go user level scheduler
    12  //     schedules goroutines onto those processes. For this reason, it is not
    13  //     possible to use syscall.Unshare. A goroutine can call `syscall.Unshare`
    14  //     from process m and the scheduler can resume that goroutine in process n,
    15  //     which has not had the unshare operation! This is a known problem with
    16  //     any system call that modifies the name space or file system context of
    17  //     only one process as opposed to the entire Go application, i.e. all of
    18  //     its processes. Examples include chroot and unshare. There has been
    19  //     lively discussion of this problem but no resolution as of yet. In sum:
    20  //     it is not possible to use `syscall.Unshare` from Go with any reasonable
    21  //     expectation of success.
    22  //
    23  //     If PROGRAM is not specified, unshare defaults to /ubin/elvish.
    24  //
    25  // Options:
    26  //     -ipc:           Unshare the IPC namespace
    27  //     -mount:         Unshare the mount namespace
    28  //     -pid:           Unshare the pid namespace
    29  //     -net:           Unshare the net namespace
    30  //     -uts:           Unshare the uts namespace
    31  //     -user:          Unshare the user namespace
    32  //     -map-root-user: Map current uid to root. Not working
    33  package main
    34  
    35  import (
    36  	"flag"
    37  	"log"
    38  	"os"
    39  	"os/exec"
    40  	"syscall"
    41  )
    42  
    43  var (
    44  	ipc     = flag.Bool("ipc", false, "Unshare the IPC namespace")
    45  	mount   = flag.Bool("mount", false, "Unshare the mount namespace")
    46  	pid     = flag.Bool("pid", false, "Unshare the pid namespace")
    47  	net     = flag.Bool("net", false, "Unshare the net namespace")
    48  	uts     = flag.Bool("uts", false, "Unshare the uts namespace")
    49  	user    = flag.Bool("user", false, "Unshare the user namespace")
    50  	maproot = flag.Bool("map-root-user", false, "Map current uid to root. Not working")
    51  )
    52  
    53  func main() {
    54  	flag.Parse()
    55  
    56  	a := flag.Args()
    57  	if len(a) == 0 {
    58  		a = []string{"/ubin/elvish", "elvish"}
    59  	}
    60  
    61  	c := exec.Command(a[0], a[1:]...)
    62  	c.SysProcAttr = &syscall.SysProcAttr{}
    63  	if *mount {
    64  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWNS
    65  	}
    66  	if *uts {
    67  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWUTS
    68  	}
    69  	if *ipc {
    70  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWIPC
    71  	}
    72  	if *net {
    73  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWNET
    74  	}
    75  	if *pid {
    76  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWPID
    77  	}
    78  	if *user {
    79  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWUSER
    80  	}
    81  
    82  	c.Stdin = os.Stdin
    83  	c.Stdout = os.Stdout
    84  	c.Stderr = os.Stderr
    85  
    86  	if err := c.Run(); err != nil {
    87  		log.Printf(err.Error())
    88  	}
    89  }