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