Source file
src/syscall/exec_libc.go
1
2
3
4
5
6
7
8
9 package syscall
10
11 import (
12 "runtime"
13 "unsafe"
14 )
15
16 type SysProcAttr struct {
17 Chroot string
18 Credential *Credential
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 func chdir(path uintptr) (err Errno)
45 func chroot1(path uintptr) (err Errno)
46 func close(fd uintptr) (err Errno)
47 func dup2child(old uintptr, new uintptr) (val uintptr, err Errno)
48 func execve(path uintptr, argv uintptr, envp uintptr) (err Errno)
49 func exit(code uintptr)
50 func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err Errno)
51 func forkx(flags uintptr) (pid uintptr, err Errno)
52 func getpid() (pid uintptr, err Errno)
53 func ioctl(fd uintptr, req uintptr, arg uintptr) (err Errno)
54 func setgid(gid uintptr) (err Errno)
55 func setgroups1(ngid uintptr, gid uintptr) (err Errno)
56 func setsid() (pid uintptr, err Errno)
57 func setuid(uid uintptr) (err Errno)
58 func setpgid(pid uintptr, pgid uintptr) (err Errno)
59 func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno)
60
61
62 func init() {
63 execveLibc = execve
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
80
81
82 var (
83 r1 uintptr
84 err1 Errno
85 nextfd int
86 i int
87 )
88
89
90
91
92 fd := make([]int, len(attr.Files))
93 nextfd = len(attr.Files)
94 for i, ufd := range attr.Files {
95 if nextfd < int(ufd) {
96 nextfd = int(ufd)
97 }
98 fd[i] = int(ufd)
99 }
100 nextfd++
101
102
103
104 runtime_BeforeFork()
105 r1, err1 = forkx(0x1)
106 if err1 != 0 {
107 runtime_AfterFork()
108 return 0, err1
109 }
110
111 if r1 != 0 {
112
113 runtime_AfterFork()
114 return int(r1), 0
115 }
116
117
118
119
120 if sys.Setsid {
121 _, err1 = setsid()
122 if err1 != 0 {
123 goto childerror
124 }
125 }
126
127
128 if sys.Setpgid || sys.Foreground {
129
130 err1 = setpgid(0, uintptr(sys.Pgid))
131 if err1 != 0 {
132 goto childerror
133 }
134 }
135
136 if sys.Foreground {
137 pgrp := _Pid_t(sys.Pgid)
138 if pgrp == 0 {
139 r1, err1 = getpid()
140 if err1 != 0 {
141 goto childerror
142 }
143
144 pgrp = _Pid_t(r1)
145 }
146
147
148 err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSPGRP), uintptr(unsafe.Pointer(&pgrp)))
149 if err1 != 0 {
150 goto childerror
151 }
152 }
153
154
155
156 runtime_AfterForkInChild()
157
158
159 if chroot != nil {
160 err1 = chroot1(uintptr(unsafe.Pointer(chroot)))
161 if err1 != 0 {
162 goto childerror
163 }
164 }
165
166
167 if cred := sys.Credential; cred != nil {
168 ngroups := uintptr(len(cred.Groups))
169 groups := uintptr(0)
170 if ngroups > 0 {
171 groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
172 }
173 if !cred.NoSetGroups {
174 err1 = setgroups1(ngroups, groups)
175 if err1 != 0 {
176 goto childerror
177 }
178 }
179 err1 = setgid(uintptr(cred.Gid))
180 if err1 != 0 {
181 goto childerror
182 }
183 err1 = setuid(uintptr(cred.Uid))
184 if err1 != 0 {
185 goto childerror
186 }
187 }
188
189
190 if dir != nil {
191 err1 = chdir(uintptr(unsafe.Pointer(dir)))
192 if err1 != 0 {
193 goto childerror
194 }
195 }
196
197
198
199 if pipe < nextfd {
200 switch runtime.GOOS {
201 case "illumos":
202 _, err1 = fcntl1(uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
203 default:
204 _, err1 = dup2child(uintptr(pipe), uintptr(nextfd))
205 if err1 != 0 {
206 goto childerror
207 }
208 _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
209 }
210 if err1 != 0 {
211 goto childerror
212 }
213 pipe = nextfd
214 nextfd++
215 }
216 for i = 0; i < len(fd); i++ {
217 if fd[i] >= 0 && fd[i] < int(i) {
218 if nextfd == pipe {
219 nextfd++
220 }
221 switch runtime.GOOS {
222 case "illumos":
223 _, err1 = fcntl1(uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
224 default:
225 _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd))
226 if err1 != 0 {
227 goto childerror
228 }
229 _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
230 }
231 if err1 != 0 {
232 goto childerror
233 }
234 fd[i] = nextfd
235 nextfd++
236 }
237 }
238
239
240 for i = 0; i < len(fd); i++ {
241 if fd[i] == -1 {
242 close(uintptr(i))
243 continue
244 }
245 if fd[i] == int(i) {
246
247
248 _, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0)
249 if err1 != 0 {
250 goto childerror
251 }
252 continue
253 }
254
255
256 _, err1 = dup2child(uintptr(fd[i]), uintptr(i))
257 if err1 != 0 {
258 goto childerror
259 }
260 }
261
262
263
264
265
266 for i = len(fd); i < 3; i++ {
267 close(uintptr(i))
268 }
269
270
271 if sys.Noctty {
272 err1 = ioctl(0, uintptr(TIOCNOTTY), 0)
273 if err1 != 0 {
274 goto childerror
275 }
276 }
277
278
279 if sys.Setctty {
280
281 if TIOCSCTTY == 0 {
282 err1 = ENOSYS
283 goto childerror
284 }
285 err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
286 if err1 != 0 {
287 goto childerror
288 }
289 }
290
291
292 err1 = execve(
293 uintptr(unsafe.Pointer(argv0)),
294 uintptr(unsafe.Pointer(&argv[0])),
295 uintptr(unsafe.Pointer(&envv[0])))
296
297 childerror:
298
299 write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
300 for {
301 exit(253)
302 }
303 }
304
View as plain text