Source file
src/syscall/exec_libc.go
Documentation: syscall
1
2
3
4
5
6
7
8
9
10 package syscall
11
12 import (
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 _, err1 = dup2child(uintptr(pipe), uintptr(nextfd))
201 if err1 != 0 {
202 goto childerror
203 }
204 fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
205 pipe = nextfd
206 nextfd++
207 }
208 for i = 0; i < len(fd); i++ {
209 if fd[i] >= 0 && fd[i] < int(i) {
210 if nextfd == pipe {
211 nextfd++
212 }
213 _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd))
214 if err1 != 0 {
215 goto childerror
216 }
217 _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
218 if err1 != 0 {
219 goto childerror
220 }
221 fd[i] = nextfd
222 nextfd++
223 }
224 }
225
226
227 for i = 0; i < len(fd); i++ {
228 if fd[i] == -1 {
229 close(uintptr(i))
230 continue
231 }
232 if fd[i] == int(i) {
233
234
235 _, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0)
236 if err1 != 0 {
237 goto childerror
238 }
239 continue
240 }
241
242
243 _, err1 = dup2child(uintptr(fd[i]), uintptr(i))
244 if err1 != 0 {
245 goto childerror
246 }
247 }
248
249
250
251
252
253 for i = len(fd); i < 3; i++ {
254 close(uintptr(i))
255 }
256
257
258 if sys.Noctty {
259 err1 = ioctl(0, uintptr(TIOCNOTTY), 0)
260 if err1 != 0 {
261 goto childerror
262 }
263 }
264
265
266 if sys.Setctty {
267
268 if TIOCSCTTY == 0 {
269 err1 = ENOSYS
270 goto childerror
271 }
272 err1 = ioctl(uintptr(sys.Ctty), uintptr(TIOCSCTTY), 0)
273 if err1 != 0 {
274 goto childerror
275 }
276 }
277
278
279 err1 = execve(
280 uintptr(unsafe.Pointer(argv0)),
281 uintptr(unsafe.Pointer(&argv[0])),
282 uintptr(unsafe.Pointer(&envv[0])))
283
284 childerror:
285
286 write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
287 for {
288 exit(253)
289 }
290 }
291
View as plain text