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