Home | History | Annotate | Download | only in runtime
      1 // Copyright 2014 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 
      5 package runtime
      6 
      7 import "unsafe"
      8 
      9 var (
     10 	libc_chdir,
     11 	libc_chroot,
     12 	libc_execve,
     13 	libc_fcntl,
     14 	libc_forkx,
     15 	libc_gethostname,
     16 	libc_getpid,
     17 	libc_ioctl,
     18 	libc_pipe,
     19 	libc_setgid,
     20 	libc_setgroups,
     21 	libc_setsid,
     22 	libc_setuid,
     23 	libc_setpgid,
     24 	libc_syscall,
     25 	libc_wait4,
     26 	pipe1 libcFunc
     27 )
     28 
     29 //go:nosplit
     30 func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
     31 	call := libcall{
     32 		fn:   fn,
     33 		n:    nargs,
     34 		args: uintptr(unsafe.Pointer(&a1)),
     35 	}
     36 	entersyscallblock(0)
     37 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     38 	exitsyscall(0)
     39 	return call.r1, call.r2, call.err
     40 }
     41 
     42 //go:nosplit
     43 func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
     44 	call := libcall{
     45 		fn:   fn,
     46 		n:    nargs,
     47 		args: uintptr(unsafe.Pointer(&a1)),
     48 	}
     49 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     50 	return call.r1, call.r2, call.err
     51 }
     52 
     53 // TODO(aram): Once we remove all instances of C calling sysvicallN, make
     54 // sysvicallN return errors and replace the body of the following functions
     55 // with calls to sysvicallN.
     56 
     57 //go:nosplit
     58 func syscall_chdir(path uintptr) (err uintptr) {
     59 	call := libcall{
     60 		fn:   uintptr(unsafe.Pointer(&libc_chdir)),
     61 		n:    1,
     62 		args: uintptr(unsafe.Pointer(&path)),
     63 	}
     64 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     65 	return call.err
     66 }
     67 
     68 //go:nosplit
     69 func syscall_chroot(path uintptr) (err uintptr) {
     70 	call := libcall{
     71 		fn:   uintptr(unsafe.Pointer(&libc_chroot)),
     72 		n:    1,
     73 		args: uintptr(unsafe.Pointer(&path)),
     74 	}
     75 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     76 	return call.err
     77 }
     78 
     79 // like close, but must not split stack, for forkx.
     80 //go:nosplit
     81 func syscall_close(fd int32) int32 {
     82 	return int32(sysvicall1(&libc_close, uintptr(fd)))
     83 }
     84 
     85 //go:nosplit
     86 func syscall_execve(path, argv, envp uintptr) (err uintptr) {
     87 	call := libcall{
     88 		fn:   uintptr(unsafe.Pointer(&libc_execve)),
     89 		n:    3,
     90 		args: uintptr(unsafe.Pointer(&path)),
     91 	}
     92 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
     93 	return call.err
     94 }
     95 
     96 // like exit, but must not split stack, for forkx.
     97 //go:nosplit
     98 func syscall_exit(code uintptr) {
     99 	sysvicall1(&libc_exit, code)
    100 }
    101 
    102 //go:nosplit
    103 func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
    104 	call := libcall{
    105 		fn:   uintptr(unsafe.Pointer(&libc_fcntl)),
    106 		n:    3,
    107 		args: uintptr(unsafe.Pointer(&fd)),
    108 	}
    109 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    110 	return call.r1, call.err
    111 }
    112 
    113 //go:nosplit
    114 func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
    115 	call := libcall{
    116 		fn:   uintptr(unsafe.Pointer(&libc_forkx)),
    117 		n:    1,
    118 		args: uintptr(unsafe.Pointer(&flags)),
    119 	}
    120 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    121 	return call.r1, call.err
    122 }
    123 
    124 func syscall_gethostname() (name string, err uintptr) {
    125 	cname := new([_MAXHOSTNAMELEN]byte)
    126 	var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
    127 	call := libcall{
    128 		fn:   uintptr(unsafe.Pointer(&libc_gethostname)),
    129 		n:    2,
    130 		args: uintptr(unsafe.Pointer(&args[0])),
    131 	}
    132 	entersyscallblock(0)
    133 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    134 	exitsyscall(0)
    135 	if call.r1 != 0 {
    136 		return "", call.err
    137 	}
    138 	cname[_MAXHOSTNAMELEN-1] = 0
    139 	return gostringnocopy(&cname[0]), 0
    140 }
    141 
    142 //go:nosplit
    143 func syscall_getpid() (pid, err uintptr) {
    144 	call := libcall{
    145 		fn:   uintptr(unsafe.Pointer(&libc_getpid)),
    146 		n:    0,
    147 		args: uintptr(unsafe.Pointer(&libc_getpid)), // it's unused but must be non-nil, otherwise crashes
    148 	}
    149 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    150 	return call.r1, call.err
    151 }
    152 
    153 //go:nosplit
    154 func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
    155 	call := libcall{
    156 		fn:   uintptr(unsafe.Pointer(&libc_ioctl)),
    157 		n:    3,
    158 		args: uintptr(unsafe.Pointer(&fd)),
    159 	}
    160 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    161 	return call.err
    162 }
    163 
    164 func syscall_pipe() (r, w, err uintptr) {
    165 	call := libcall{
    166 		fn:   uintptr(unsafe.Pointer(&pipe1)),
    167 		n:    0,
    168 		args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes
    169 	}
    170 	entersyscallblock(0)
    171 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    172 	exitsyscall(0)
    173 	return call.r1, call.r2, call.err
    174 }
    175 
    176 // This is syscall.RawSyscall, it exists to satisfy some build dependency,
    177 // but it doesn't work correctly.
    178 //
    179 // DO NOT USE!
    180 //
    181 // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
    182 func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
    183 	call := libcall{
    184 		fn:   uintptr(unsafe.Pointer(&libc_syscall)),
    185 		n:    4,
    186 		args: uintptr(unsafe.Pointer(&trap)),
    187 	}
    188 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    189 	return call.r1, call.r2, call.err
    190 }
    191 
    192 //go:nosplit
    193 func syscall_setgid(gid uintptr) (err uintptr) {
    194 	call := libcall{
    195 		fn:   uintptr(unsafe.Pointer(&libc_setgid)),
    196 		n:    1,
    197 		args: uintptr(unsafe.Pointer(&gid)),
    198 	}
    199 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    200 	return call.err
    201 }
    202 
    203 //go:nosplit
    204 func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
    205 	call := libcall{
    206 		fn:   uintptr(unsafe.Pointer(&libc_setgroups)),
    207 		n:    2,
    208 		args: uintptr(unsafe.Pointer(&ngid)),
    209 	}
    210 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    211 	return call.err
    212 }
    213 
    214 //go:nosplit
    215 func syscall_setsid() (pid, err uintptr) {
    216 	call := libcall{
    217 		fn:   uintptr(unsafe.Pointer(&libc_setsid)),
    218 		n:    0,
    219 		args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes
    220 	}
    221 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    222 	return call.r1, call.err
    223 }
    224 
    225 //go:nosplit
    226 func syscall_setuid(uid uintptr) (err uintptr) {
    227 	call := libcall{
    228 		fn:   uintptr(unsafe.Pointer(&libc_setuid)),
    229 		n:    1,
    230 		args: uintptr(unsafe.Pointer(&uid)),
    231 	}
    232 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    233 	return call.err
    234 }
    235 
    236 //go:nosplit
    237 func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
    238 	call := libcall{
    239 		fn:   uintptr(unsafe.Pointer(&libc_setpgid)),
    240 		n:    2,
    241 		args: uintptr(unsafe.Pointer(&pid)),
    242 	}
    243 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    244 	return call.err
    245 }
    246 
    247 // This is syscall.Syscall, it exists to satisfy some build dependency,
    248 // but it doesn't work correctly.
    249 //
    250 // DO NOT USE!
    251 //
    252 // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
    253 func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
    254 	call := libcall{
    255 		fn:   uintptr(unsafe.Pointer(&libc_syscall)),
    256 		n:    4,
    257 		args: uintptr(unsafe.Pointer(&trap)),
    258 	}
    259 	entersyscallblock(0)
    260 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    261 	exitsyscall(0)
    262 	return call.r1, call.r2, call.err
    263 }
    264 
    265 func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
    266 	call := libcall{
    267 		fn:   uintptr(unsafe.Pointer(&libc_wait4)),
    268 		n:    4,
    269 		args: uintptr(unsafe.Pointer(&pid)),
    270 	}
    271 	entersyscallblock(0)
    272 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    273 	exitsyscall(0)
    274 	return int(call.r1), call.err
    275 }
    276 
    277 //go:nosplit
    278 func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
    279 	call := libcall{
    280 		fn:   uintptr(unsafe.Pointer(&libc_write)),
    281 		n:    3,
    282 		args: uintptr(unsafe.Pointer(&fd)),
    283 	}
    284 	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
    285 	return call.r1, call.err
    286 }
    287