github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/syscall/exec_bsd.go (about) 1 // Copyright 2011 The Go 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 // +build darwin dragonfly freebsd netbsd openbsd 6 7 package syscall 8 9 import ( 10 "unsafe" 11 ) 12 13 type SysProcAttr struct { 14 Chroot string // Chroot. 15 Credential *Credential // Credential. 16 Ptrace bool // Enable tracing. 17 Setsid bool // Create session. 18 Setpgid bool // Set process group ID to Pgid, or, if Pgid == 0, to new pid. 19 Setctty bool // Set controlling terminal to fd Ctty 20 Noctty bool // Detach fd 0 from controlling terminal 21 Ctty int // Controlling TTY fd 22 Foreground bool // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY) 23 Pgid int // Child's process group ID if Setpgid. 24 } 25 26 // Implemented in runtime package. 27 func runtime_BeforeFork() 28 func runtime_AfterFork() 29 30 // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. 31 // If a dup or exec fails, write the errno error to pipe. 32 // (Pipe is close-on-exec so if exec succeeds, it will be closed.) 33 // In the child, this function must not acquire any locks, because 34 // they might have been locked at the time of the fork. This means 35 // no rescheduling, no malloc calls, and no new stack segments. 36 // For the same reason compiler does not race instrument it. 37 // The calls to RawSyscall are okay because they are assembly 38 // functions that do not grow the stack. 39 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) { 40 // Declare all variables at top in case any 41 // declarations require heap allocation (e.g., err1). 42 var ( 43 r1 Pid_t 44 err1 Errno 45 nextfd int 46 i int 47 ) 48 49 // guard against side effects of shuffling fds below. 50 // Make sure that nextfd is beyond any currently open files so 51 // that we can't run the risk of overwriting any of them. 52 fd := make([]int, len(attr.Files)) 53 nextfd = len(attr.Files) 54 for i, ufd := range attr.Files { 55 if nextfd < int(ufd) { 56 nextfd = int(ufd) 57 } 58 fd[i] = int(ufd) 59 } 60 nextfd++ 61 62 // About to call fork. 63 // No more allocation or calls of non-assembly functions. 64 runtime_BeforeFork() 65 r1, err1 = raw_fork() 66 if err1 != 0 { 67 runtime_AfterFork() 68 return 0, err1 69 } 70 71 if r1 != 0 { 72 // parent; return PID 73 runtime_AfterFork() 74 return int(r1), 0 75 } 76 77 // Fork succeeded, now in child. 78 79 // Enable tracing if requested. 80 if sys.Ptrace { 81 err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil) 82 if err1 != 0 { 83 goto childerror 84 } 85 } 86 87 // Session ID 88 if sys.Setsid { 89 err1 = raw_setsid() 90 if err1 != 0 { 91 goto childerror 92 } 93 } 94 95 // Set process group 96 if sys.Setpgid || sys.Foreground { 97 // Place child in process group. 98 err1 = raw_setpgid(0, sys.Pgid) 99 if err1 != 0 { 100 goto childerror 101 } 102 } 103 104 if sys.Foreground { 105 pgrp := Pid_t(sys.Pgid) 106 if pgrp == 0 { 107 pgrp = raw_getpid() 108 } 109 110 // Place process group in foreground. 111 _, err1 = raw_ioctl_ptr(sys.Ctty, TIOCSPGRP, unsafe.Pointer(&pgrp)) 112 if err1 != 0 { 113 goto childerror 114 } 115 } 116 117 // Chroot 118 if chroot != nil { 119 err1 = raw_chroot(chroot) 120 if err1 != 0 { 121 goto childerror 122 } 123 } 124 125 // User and groups 126 if cred := sys.Credential; cred != nil { 127 ngroups := len(cred.Groups) 128 if ngroups == 0 { 129 err2 := setgroups(0, nil) 130 if err2 == nil { 131 err1 = 0 132 } else { 133 err1 = err2.(Errno) 134 } 135 } else { 136 groups := make([]Gid_t, ngroups) 137 for i, v := range cred.Groups { 138 groups[i] = Gid_t(v) 139 } 140 err2 := setgroups(ngroups, &groups[0]) 141 if err2 == nil { 142 err1 = 0 143 } else { 144 err1 = err2.(Errno) 145 } 146 } 147 if err1 != 0 { 148 goto childerror 149 } 150 err2 := Setgid(int(cred.Gid)) 151 if err2 != nil { 152 err1 = err2.(Errno) 153 goto childerror 154 } 155 err2 = Setuid(int(cred.Uid)) 156 if err2 != nil { 157 err1 = err2.(Errno) 158 goto childerror 159 } 160 } 161 162 // Chdir 163 if dir != nil { 164 err1 = raw_chdir(dir) 165 if err1 != 0 { 166 goto childerror 167 } 168 } 169 170 // Pass 1: look for fd[i] < i and move those up above len(fd) 171 // so that pass 2 won't stomp on an fd it needs later. 172 if pipe < nextfd { 173 err1 = raw_dup2(pipe, nextfd) 174 if err1 != 0 { 175 goto childerror 176 } 177 raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) 178 pipe = nextfd 179 nextfd++ 180 } 181 for i = 0; i < len(fd); i++ { 182 if fd[i] >= 0 && fd[i] < int(i) { 183 err1 = raw_dup2(fd[i], nextfd) 184 if err1 != 0 { 185 goto childerror 186 } 187 raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) 188 fd[i] = nextfd 189 nextfd++ 190 if nextfd == pipe { // don't stomp on pipe 191 nextfd++ 192 } 193 } 194 } 195 196 // Pass 2: dup fd[i] down onto i. 197 for i = 0; i < len(fd); i++ { 198 if fd[i] == -1 { 199 raw_close(i) 200 continue 201 } 202 if fd[i] == int(i) { 203 // dup2(i, i) won't clear close-on-exec flag on Linux, 204 // probably not elsewhere either. 205 _, err1 = raw_fcntl(fd[i], F_SETFD, 0) 206 if err1 != 0 { 207 goto childerror 208 } 209 continue 210 } 211 // The new fd is created NOT close-on-exec, 212 // which is exactly what we want. 213 err1 = raw_dup2(fd[i], i) 214 if err1 != 0 { 215 goto childerror 216 } 217 } 218 219 // By convention, we don't close-on-exec the fds we are 220 // started with, so if len(fd) < 3, close 0, 1, 2 as needed. 221 // Programs that know they inherit fds >= 3 will need 222 // to set them close-on-exec. 223 for i = len(fd); i < 3; i++ { 224 raw_close(i) 225 } 226 227 // Detach fd 0 from tty 228 if sys.Noctty { 229 _, err1 = raw_ioctl(0, TIOCNOTTY, 0) 230 if err1 != 0 { 231 goto childerror 232 } 233 } 234 235 // Set the controlling TTY to Ctty 236 if sys.Setctty { 237 _, err1 = raw_ioctl(sys.Ctty, TIOCSCTTY, 0) 238 if err1 != 0 { 239 goto childerror 240 } 241 } 242 243 // Time to exec. 244 err1 = raw_execve(argv0, &argv[0], &envv[0]) 245 246 childerror: 247 // send error code on pipe 248 raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) 249 for { 250 raw_exit(253) 251 } 252 } 253 254 // Try to open a pipe with O_CLOEXEC set on both file descriptors. 255 func forkExecPipe(p []int) error { 256 err := Pipe(p) 257 if err != nil { 258 return err 259 } 260 _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC) 261 if err != nil { 262 return err 263 } 264 _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC) 265 return err 266 }