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