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