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