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