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