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 pgrp _C_int
63 cred *Credential
64 ngroups, groups uintptr
65 )
66
67 rlim := origRlimitNofile.Load()
68
69
70
71
72 fd := make([]int, len(attr.Files))
73 nextfd = len(attr.Files)
74 for i, ufd := range attr.Files {
75 if nextfd < int(ufd) {
76 nextfd = int(ufd)
77 }
78 fd[i] = int(ufd)
79 }
80 nextfd++
81
82
83
84 runtime_BeforeFork()
85 r1, _, err1 = RawSyscall(SYS_FORK, 0, 0, 0)
86 if err1 != 0 {
87 runtime_AfterFork()
88 return 0, err1
89 }
90
91 if r1 != 0 {
92
93 runtime_AfterFork()
94 return int(r1), 0
95 }
96
97
98
99
100 if sys.Ptrace {
101 _, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
102 if err1 != 0 {
103 goto childerror
104 }
105 }
106
107
108 if sys.Setsid {
109 _, _, err1 = RawSyscall(SYS_SETSID, 0, 0, 0)
110 if err1 != 0 {
111 goto childerror
112 }
113 }
114
115
116 if sys.Setpgid || sys.Foreground {
117
118 _, _, err1 = RawSyscall(SYS_SETPGID, 0, uintptr(sys.Pgid), 0)
119 if err1 != 0 {
120 goto childerror
121 }
122 }
123
124 if sys.Foreground {
125
126
127 pgrp = _C_int(sys.Pgid)
128 if pgrp == 0 {
129 r1, _, err1 = RawSyscall(SYS_GETPID, 0, 0, 0)
130 if err1 != 0 {
131 goto childerror
132 }
133
134 pgrp = _C_int(r1)
135 }
136
137
138 _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
139 if err1 != 0 {
140 goto childerror
141 }
142 }
143
144
145
146 runtime_AfterForkInChild()
147
148
149 if chroot != nil {
150 _, _, err1 = RawSyscall(SYS_CHROOT, uintptr(unsafe.Pointer(chroot)), 0, 0)
151 if err1 != 0 {
152 goto childerror
153 }
154 }
155
156
157 if cred = sys.Credential; cred != nil {
158 ngroups = uintptr(len(cred.Groups))
159 groups = uintptr(0)
160 if ngroups > 0 {
161 groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
162 }
163 if !cred.NoSetGroups {
164 _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0)
165 if err1 != 0 {
166 goto childerror
167 }
168 }
169 _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
170 if err1 != 0 {
171 goto childerror
172 }
173 _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
174 if err1 != 0 {
175 goto childerror
176 }
177 }
178
179
180 if dir != nil {
181 _, _, err1 = RawSyscall(SYS_CHDIR, uintptr(unsafe.Pointer(dir)), 0, 0)
182 if err1 != 0 {
183 goto childerror
184 }
185 }
186
187
188
189 if pipe < nextfd {
190 if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") {
191 _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
192 } else if runtime.GOOS == "dragonfly" {
193 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
194 } else {
195 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(pipe), uintptr(nextfd), 0)
196 if err1 != 0 {
197 goto childerror
198 }
199 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
200 }
201 if err1 != 0 {
202 goto childerror
203 }
204 pipe = nextfd
205 nextfd++
206 }
207 for i = 0; i < len(fd); i++ {
208 if fd[i] >= 0 && fd[i] < i {
209 if nextfd == pipe {
210 nextfd++
211 }
212 if runtime.GOOS == "netbsd" || (runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64") {
213 _, _, err1 = RawSyscall(_SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
214 } else if runtime.GOOS == "dragonfly" {
215 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
216 } else {
217 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(nextfd), 0)
218 if err1 != 0 {
219 goto childerror
220 }
221 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
222 }
223 if err1 != 0 {
224 goto childerror
225 }
226 fd[i] = nextfd
227 nextfd++
228 }
229 }
230
231
232 for i = 0; i < len(fd); i++ {
233 if fd[i] == -1 {
234 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
235 continue
236 }
237 if fd[i] == i {
238
239
240 _, _, err1 = RawSyscall(SYS_FCNTL, uintptr(fd[i]), F_SETFD, 0)
241 if err1 != 0 {
242 goto childerror
243 }
244 continue
245 }
246
247
248 _, _, err1 = RawSyscall(SYS_DUP2, uintptr(fd[i]), uintptr(i), 0)
249 if err1 != 0 {
250 goto childerror
251 }
252 }
253
254
255
256
257
258 for i = len(fd); i < 3; i++ {
259 RawSyscall(SYS_CLOSE, uintptr(i), 0, 0)
260 }
261
262
263 if sys.Noctty {
264 _, _, err1 = RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
265 if err1 != 0 {
266 goto childerror
267 }
268 }
269
270
271 if sys.Setctty {
272 _, _, err1 = RawSyscall(SYS_IOCTL, uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
273 if err1 != 0 {
274 goto childerror
275 }
276 }
277
278
279 if rlim != nil {
280 RawSyscall(SYS_SETRLIMIT, uintptr(RLIMIT_NOFILE), uintptr(unsafe.Pointer(rlim)), 0)
281 }
282
283
284 _, _, err1 = RawSyscall(SYS_EXECVE,
285 uintptr(unsafe.Pointer(argv0)),
286 uintptr(unsafe.Pointer(&argv[0])),
287 uintptr(unsafe.Pointer(&envv[0])))
288
289 childerror:
290
291 RawSyscall(SYS_WRITE, uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
292 for {
293 RawSyscall(SYS_EXIT, 253, 0, 0)
294 }
295 }
296
297
298 func forkAndExecFailureCleanup(attr *ProcAttr, sys *SysProcAttr) {
299
300 }
301
View as plain text