github.com/rminnich/u-root@v7.0.0+incompatible/cmds/core/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  )
    51  
    52  func main() {
    53  	flag.Parse()
    54  
    55  	a := flag.Args()
    56  	if len(a) == 0 {
    57  		a = []string{"/ubin/elvish", "elvish"}
    58  	}
    59  
    60  	c := exec.Command(a[0], a[1:]...)
    61  	c.SysProcAttr = &syscall.SysProcAttr{}
    62  	if *mount {
    63  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWNS
    64  	}
    65  	if *uts {
    66  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWUTS
    67  	}
    68  	if *ipc {
    69  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWIPC
    70  	}
    71  	if *net {
    72  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWNET
    73  	}
    74  	if *pid {
    75  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWPID
    76  	}
    77  	if *user {
    78  		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWUSER
    79  	}
    80  
    81  	c.Stdin = os.Stdin
    82  	c.Stdout = os.Stdout
    83  	c.Stderr = os.Stderr
    84  
    85  	if err := c.Run(); err != nil {
    86  		log.Fatalf("%v", err)
    87  	}
    88  }