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 }