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