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