Source file
src/syscall/exec_bsd.go
1
2
3
4
5
6
7 package syscall
8
9 import (
10 "runtime"
11 "unsafe"
12 )
13
14 type SysProcAttr struct {
15 Chroot string
16 Credential *Credential
17 Ptrace bool
18 Setsid bool
19
20
21 Setpgid bool
22
23
24
25
26 Setctty bool
27 Noctty bool
28 Ctty int
29
30
31
32
33
34 Foreground bool
35 Pgid int
36 }
37
38
39 func runtime_BeforeFork()
40 func runtime_AfterFork()
41 func runtime_AfterForkInChild()
42
43
44
45
46
47
48
49
50
51
52
53
54 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
55
56
57 var (
58 r1 uintptr
59 err1 Errno
60 nextfd int
61 i int
62 )
63
64
65
66
67 fd := make([]int, len(attr.Files))
68 nextfd = len(attr.Files)
69 for i, ufd := range attr.Files {
70 if nextfd < int(ufd) {
71 nextfd = int(ufd)
72 }
73 fd[i] = int(ufd)
74 }
75 nextfd++
76
77
78
79 runtime_BeforeFork()
80 r1, _, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
81 if err1 != 0 {
82 runtime_AfterFork()
83 return 0, err1
84 }
85
86 if r1 != 0 {
87
88 runtime_AfterFork()
89 return int(r1), 0
90 }
91
92
93
94
95 if sys.Ptrace {
96 _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
97 if err1 != 0 {
98 goto childerror
99 }
100 }
101
102
103 if sys.Setsid {
104 _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
105 if err1 != 0 {
106 goto childerror
107 }
108 }
109
110
111 if sys.Setpgid || sys.Foreground {
112
113 _, _, err1 = RawSyscall(SYS_SETPGID, 0, uintptr(sys.Pgid), 0)
114 if err1 != 0 {
115 goto childerror
116 }
117 }
118
119 if sys.Foreground {
120
121
122 pgrp := _C_int(sys.Pgid)
123 if pgrp == 0 {
124 r1, _, err1 = RawSyscall(SYS_GETPID, 0, 0, 0)
125 if err1 != 0 {
126 goto childerror
127 }
128
129 pgrp = _C_int(r1)
130 }
131
132
133 _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
134 if err1 != 0 {
135 goto childerror
136 }
137 }
138
139
140
141 runtime_AfterForkInChild()
142
143
144 if chroot != nil {
145 _, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
146 if err1 != 0 {
147 goto childerror
148 }
149 }
150
151
152 if cred := sys.Credential; cred != nil {
153 ngroups := uintptr(len(cred.Groups))
154 groups := uintptr(0)
155 if ngroups > 0 {
156 groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
157 }
158 if !cred.NoSetGroups {
159 _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
160 if err1 != 0 {
161 goto childerror
162 }
163 }
164 _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
165 if err1 != 0 {
166 goto childerror
167 }
168 _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
169 if err1 != 0 {
170 goto childerror
171 }
172 }
173
174
175 if dir != nil {
176 _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
177 if err1 != 0 {
178 goto childerror
179 }
180 }
181
182
183
184 if pipe < nextfd {
185 if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") {
186 _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
187 } else if runtime.GOOS == "dragonfly" {
188 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
189 } else {
190 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
191 if err1 != 0 {
192 goto childerror
193 }
194 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
195 }
196 if err1 != 0 {
197 goto childerror
198 }
199 pipe = nextfd
200 nextfd++
201 }
202 for i = 0; i < len(fd); i++ {
203 if fd[i] >= 0 && fd[i] < i {
204 if nextfd == pipe {
205 nextfd++
206 }
207 if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") {
208 _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
209 } else if runtime.GOOS == "dragonfly" {
210 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
211 } else {
212 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
213 if err1 != 0 {
214 goto childerror
215 }
216 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
217 }
218 if err1 != 0 {
219 goto childerror
220 }
221 fd[i] = nextfd
222 nextfd++
223 }
224 }
225
226
227 for i = 0; i < len(fd); i++ {
228 if fd[i] == -1 {
229 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
230 continue
231 }
232 if fd[i] == i {
233
234
235 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
236 if err1 != 0 {
237 goto childerror
238 }
239 continue
240 }
241
242
243 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
244 if err1 != 0 {
245 goto childerror
246 }
247 }
248
249
250
251
252
253 for i = len(fd); i < 3; i++ {
254 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
255 }
256
257
258 if sys.Noctty {
259 _, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
260 if err1 != 0 {
261 goto childerror
262 }
263 }
264
265
266 if sys.Setctty {
267 _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
268 if err1 != 0 {
269 goto childerror
270 }
271 }
272
273
274 _, _, err1 = RawSyscall(SYS_EXECVE,
275 uintptr(unsafe.Pointer(argv0)),
276 uintptr(unsafe.Pointer(&argv[0])),
277 uintptr(unsafe.Pointer(&envv[0])))
278
279 childerror:
280
281 RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
282 for {
283 RawSyscall(SYS_EXIT, 253, 0, 0)
284 }
285 }
286
View as plain text