github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+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 }