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