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