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