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