1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package runtime
6
7import "unsafe"
8
9// This file handles some syscalls from the syscall package
10// Especially, syscalls use during forkAndExecInChild which must not split the stack
11
12//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o"
13//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o"
14//go:cgo_import_dynamic libc_dup2 dup2 "libc.a/shr_64.o"
15//go:cgo_import_dynamic libc_execve execve "libc.a/shr_64.o"
16//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o"
17//go:cgo_import_dynamic libc_fork fork "libc.a/shr_64.o"
18//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o"
19//go:cgo_import_dynamic libc_setgid setgid "libc.a/shr_64.o"
20//go:cgo_import_dynamic libc_setgroups setgroups "libc.a/shr_64.o"
21//go:cgo_import_dynamic libc_setsid setsid "libc.a/shr_64.o"
22//go:cgo_import_dynamic libc_setuid setuid "libc.a/shr_64.o"
23//go:cgo_import_dynamic libc_setpgid setpgid "libc.a/shr_64.o"
24
25//go:linkname libc_chdir libc_chdir
26//go:linkname libc_chroot libc_chroot
27//go:linkname libc_dup2 libc_dup2
28//go:linkname libc_execve libc_execve
29//go:linkname libc_fcntl libc_fcntl
30//go:linkname libc_fork libc_fork
31//go:linkname libc_ioctl libc_ioctl
32//go:linkname libc_setgid libc_setgid
33//go:linkname libc_setgroups libc_setgroups
34//go:linkname libc_setsid libc_setsid
35//go:linkname libc_setuid libc_setuid
36//go:linkname libc_setpgid libc_setpgid
37
38var (
39	libc_chdir,
40	libc_chroot,
41	libc_dup2,
42	libc_execve,
43	libc_fcntl,
44	libc_fork,
45	libc_ioctl,
46	libc_setgid,
47	libc_setgroups,
48	libc_setsid,
49	libc_setuid,
50	libc_setpgid libFunc
51)
52
53// In syscall_syscall6 and syscall_rawsyscall6, r2 is always 0
54// as it's never used on AIX
55// TODO: remove r2 from zsyscall_aix_$GOARCH.go
56
57// Syscall is needed because some packages (like net) need it too.
58// The best way is to return EINVAL and let Golang handles its failure
59// If the syscall can't fail, this function can redirect it to a real syscall.
60//
61// This is exported via linkname to assembly in the syscall package.
62//
63//go:nosplit
64//go:linkname syscall_Syscall
65func syscall_Syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
66	return 0, 0, _EINVAL
67}
68
69// This is syscall.RawSyscall, it exists to satisfy some build dependency,
70// but it doesn't work.
71//
72// This is exported via linkname to assembly in the syscall package.
73//
74//go:linkname syscall_RawSyscall
75func syscall_RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
76	panic("RawSyscall not available on AIX")
77}
78
79// This is exported via linkname to assembly in the syscall package.
80//
81//go:nosplit
82//go:cgo_unsafe_args
83//go:linkname syscall_syscall6
84func syscall_syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
85	c := libcall{
86		fn:   fn,
87		n:    nargs,
88		args: uintptr(unsafe.Pointer(&a1)),
89	}
90
91	entersyscallblock()
92	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
93	exitsyscall()
94	return c.r1, 0, c.err
95}
96
97// This is exported via linkname to assembly in the syscall package.
98//
99//go:nosplit
100//go:cgo_unsafe_args
101//go:linkname syscall_rawSyscall6
102func syscall_rawSyscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
103	c := libcall{
104		fn:   fn,
105		n:    nargs,
106		args: uintptr(unsafe.Pointer(&a1)),
107	}
108
109	asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(&c))
110
111	return c.r1, 0, c.err
112}
113
114//go:linkname syscall_chdir syscall.chdir
115//go:nosplit
116func syscall_chdir(path uintptr) (err uintptr) {
117	_, err = syscall1(&libc_chdir, path)
118	return
119}
120
121//go:linkname syscall_chroot1 syscall.chroot1
122//go:nosplit
123func syscall_chroot1(path uintptr) (err uintptr) {
124	_, err = syscall1(&libc_chroot, path)
125	return
126}
127
128// like close, but must not split stack, for fork.
129//go:linkname syscall_close syscall.close
130//go:nosplit
131func syscall_close(fd int32) int32 {
132	_, err := syscall1(&libc_close, uintptr(fd))
133	return int32(err)
134}
135
136//go:linkname syscall_dup2child syscall.dup2child
137//go:nosplit
138func syscall_dup2child(old, new uintptr) (val, err uintptr) {
139	val, err = syscall2(&libc_dup2, old, new)
140	return
141}
142
143//go:linkname syscall_execve syscall.execve
144//go:nosplit
145func syscall_execve(path, argv, envp uintptr) (err uintptr) {
146	_, err = syscall3(&libc_execve, path, argv, envp)
147	return
148}
149
150// like exit, but must not split stack, for fork.
151//go:linkname syscall_exit syscall.exit
152//go:nosplit
153func syscall_exit(code uintptr) {
154	syscall1(&libc_exit, code)
155}
156
157//go:linkname syscall_fcntl1 syscall.fcntl1
158//go:nosplit
159func syscall_fcntl1(fd, cmd, arg uintptr) (val, err uintptr) {
160	val, err = syscall3(&libc_fcntl, fd, cmd, arg)
161	return
162
163}
164
165//go:linkname syscall_forkx syscall.forkx
166//go:nosplit
167func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
168	pid, err = syscall1(&libc_fork, flags)
169	return
170}
171
172//go:linkname syscall_getpid syscall.getpid
173//go:nosplit
174func syscall_getpid() (pid, err uintptr) {
175	pid, err = syscall0(&libc_getpid)
176	return
177}
178
179//go:linkname syscall_ioctl syscall.ioctl
180//go:nosplit
181func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
182	_, err = syscall3(&libc_ioctl, fd, req, arg)
183	return
184}
185
186//go:linkname syscall_setgid syscall.setgid
187//go:nosplit
188func syscall_setgid(gid uintptr) (err uintptr) {
189	_, err = syscall1(&libc_setgid, gid)
190	return
191}
192
193//go:linkname syscall_setgroups1 syscall.setgroups1
194//go:nosplit
195func syscall_setgroups1(ngid, gid uintptr) (err uintptr) {
196	_, err = syscall2(&libc_setgroups, ngid, gid)
197	return
198}
199
200//go:linkname syscall_setsid syscall.setsid
201//go:nosplit
202func syscall_setsid() (pid, err uintptr) {
203	pid, err = syscall0(&libc_setsid)
204	return
205}
206
207//go:linkname syscall_setuid syscall.setuid
208//go:nosplit
209func syscall_setuid(uid uintptr) (err uintptr) {
210	_, err = syscall1(&libc_setuid, uid)
211	return
212}
213
214//go:linkname syscall_setpgid syscall.setpgid
215//go:nosplit
216func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
217	_, err = syscall2(&libc_setpgid, pid, pgid)
218	return
219}
220
221//go:linkname syscall_write1 syscall.write1
222//go:nosplit
223func syscall_write1(fd, buf, nbyte uintptr) (n, err uintptr) {
224	n, err = syscall3(&libc_write, fd, buf, nbyte)
225	return
226}
227