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