1// Copyright 2009 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// Linux system calls. 6// This file is compiled as ordinary Go code, 7// but it is also input to mksyscall, 8// which parses the //sys lines and generates system call stubs. 9// Note that sometimes we use a lowercase //sys name and 10// wrap it in our own nicer implementation. 11 12package syscall 13 14import ( 15 "internal/itoa" 16 runtimesyscall "internal/runtime/syscall" 17 "runtime" 18 "unsafe" 19) 20 21// Pull in entersyscall/exitsyscall for Syscall/Syscall6. 22// 23// Note that this can't be a push linkname because the runtime already has a 24// nameless linkname to export to assembly here and in x/sys. Additionally, 25// entersyscall fetches the caller PC and SP and thus can't have a wrapper 26// inbetween. 27 28//go:linkname runtime_entersyscall runtime.entersyscall 29func runtime_entersyscall() 30 31//go:linkname runtime_exitsyscall runtime.exitsyscall 32func runtime_exitsyscall() 33 34// N.B. For the Syscall functions below: 35// 36// //go:uintptrkeepalive because the uintptr argument may be converted pointers 37// that need to be kept alive in the caller. 38// 39// //go:nosplit because stack copying does not account for uintptrkeepalive, so 40// the stack must not grow. Stack copying cannot blindly assume that all 41// uintptr arguments are pointers, because some values may look like pointers, 42// but not really be pointers, and adjusting their value would break the call. 43// 44// //go:norace, on RawSyscall, to avoid race instrumentation if RawSyscall is 45// called after fork, or from a signal handler. 46// 47// //go:linkname to ensure ABI wrappers are generated for external callers 48// (notably x/sys/unix assembly). 49 50//go:uintptrkeepalive 51//go:nosplit 52//go:norace 53//go:linkname RawSyscall 54func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 55 return RawSyscall6(trap, a1, a2, a3, 0, 0, 0) 56} 57 58//go:uintptrkeepalive 59//go:nosplit 60//go:norace 61//go:linkname RawSyscall6 62func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 63 var errno uintptr 64 r1, r2, errno = runtimesyscall.Syscall6(trap, a1, a2, a3, a4, a5, a6) 65 err = Errno(errno) 66 return 67} 68 69//go:uintptrkeepalive 70//go:nosplit 71//go:linkname Syscall 72func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 73 runtime_entersyscall() 74 // N.B. Calling RawSyscall here is unsafe with atomic coverage 75 // instrumentation and race mode. 76 // 77 // Coverage instrumentation will add a sync/atomic call to RawSyscall. 78 // Race mode will add race instrumentation to sync/atomic. Race 79 // instrumentation requires a P, which we no longer have. 80 // 81 // RawSyscall6 is fine because it is implemented in assembly and thus 82 // has no coverage instrumentation. 83 // 84 // This is typically not a problem in the runtime because cmd/go avoids 85 // adding coverage instrumentation to the runtime in race mode. 86 r1, r2, err = RawSyscall6(trap, a1, a2, a3, 0, 0, 0) 87 runtime_exitsyscall() 88 return 89} 90 91//go:uintptrkeepalive 92//go:nosplit 93//go:linkname Syscall6 94func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 95 runtime_entersyscall() 96 r1, r2, err = RawSyscall6(trap, a1, a2, a3, a4, a5, a6) 97 runtime_exitsyscall() 98 return 99} 100 101func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) 102func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1 uintptr, err Errno) 103 104/* 105 * Wrapped 106 */ 107 108func Access(path string, mode uint32) (err error) { 109 return Faccessat(_AT_FDCWD, path, mode, 0) 110} 111 112func Chmod(path string, mode uint32) (err error) { 113 return Fchmodat(_AT_FDCWD, path, mode, 0) 114} 115 116func Chown(path string, uid int, gid int) (err error) { 117 return Fchownat(_AT_FDCWD, path, uid, gid, 0) 118} 119 120func Creat(path string, mode uint32) (fd int, err error) { 121 return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) 122} 123 124func EpollCreate(size int) (fd int, err error) { 125 if size <= 0 { 126 return -1, EINVAL 127 } 128 return EpollCreate1(0) 129} 130 131func isGroupMember(gid int) bool { 132 groups, err := Getgroups() 133 if err != nil { 134 return false 135 } 136 137 for _, g := range groups { 138 if g == gid { 139 return true 140 } 141 } 142 return false 143} 144 145func isCapDacOverrideSet() bool { 146 const _CAP_DAC_OVERRIDE = 1 147 var c caps 148 c.hdr.version = _LINUX_CAPABILITY_VERSION_3 149 150 _, _, err := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(&c.hdr)), uintptr(unsafe.Pointer(&c.data[0])), 0) 151 152 return err == 0 && c.data[0].effective&capToMask(_CAP_DAC_OVERRIDE) != 0 153} 154 155//sys faccessat(dirfd int, path string, mode uint32) (err error) 156//sys faccessat2(dirfd int, path string, mode uint32, flags int) (err error) = _SYS_faccessat2 157 158func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { 159 if flags == 0 { 160 return faccessat(dirfd, path, mode) 161 } 162 163 // Attempt to use the newer faccessat2, which supports flags directly, 164 // falling back if it doesn't exist. 165 // 166 // Don't attempt on Android, which does not allow faccessat2 through 167 // its seccomp policy [1] on any version of Android as of 2022-12-20. 168 // 169 // [1] https://cs.android.com/android/platform/superproject/+/master:bionic/libc/SECCOMP_BLOCKLIST_APP.TXT;l=4;drc=dbb8670dfdcc677f7e3b9262e93800fa14c4e417 170 if runtime.GOOS != "android" { 171 if err := faccessat2(dirfd, path, mode, flags); err != ENOSYS && err != EPERM { 172 return err 173 } 174 } 175 176 // The Linux kernel faccessat system call does not take any flags. 177 // The glibc faccessat implements the flags itself; see 178 // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/faccessat.c;hb=HEAD 179 // Because people naturally expect syscall.Faccessat to act 180 // like C faccessat, we do the same. 181 182 if flags & ^(_AT_SYMLINK_NOFOLLOW|_AT_EACCESS) != 0 { 183 return EINVAL 184 } 185 186 var st Stat_t 187 if err := fstatat(dirfd, path, &st, flags&_AT_SYMLINK_NOFOLLOW); err != nil { 188 return err 189 } 190 191 mode &= 7 192 if mode == 0 { 193 return nil 194 } 195 196 // Fallback to checking permission bits. 197 var uid int 198 if flags&_AT_EACCESS != 0 { 199 uid = Geteuid() 200 if uid != 0 && isCapDacOverrideSet() { 201 // If CAP_DAC_OVERRIDE is set, file access check is 202 // done by the kernel in the same way as for root 203 // (see generic_permission() in the Linux sources). 204 uid = 0 205 } 206 } else { 207 uid = Getuid() 208 } 209 210 if uid == 0 { 211 if mode&1 == 0 { 212 // Root can read and write any file. 213 return nil 214 } 215 if st.Mode&0111 != 0 { 216 // Root can execute any file that anybody can execute. 217 return nil 218 } 219 return EACCES 220 } 221 222 var fmode uint32 223 if uint32(uid) == st.Uid { 224 fmode = (st.Mode >> 6) & 7 225 } else { 226 var gid int 227 if flags&_AT_EACCESS != 0 { 228 gid = Getegid() 229 } else { 230 gid = Getgid() 231 } 232 233 if uint32(gid) == st.Gid || isGroupMember(int(st.Gid)) { 234 fmode = (st.Mode >> 3) & 7 235 } else { 236 fmode = st.Mode & 7 237 } 238 } 239 240 if fmode&mode == mode { 241 return nil 242 } 243 244 return EACCES 245} 246 247//sys fchmodat(dirfd int, path string, mode uint32) (err error) 248//sys fchmodat2(dirfd int, path string, mode uint32, flags int) (err error) = _SYS_fchmodat2 249 250func Fchmodat(dirfd int, path string, mode uint32, flags int) error { 251 // Linux fchmodat doesn't support the flags parameter, but fchmodat2 does. 252 // Try fchmodat2 if flags are specified. 253 if flags != 0 { 254 err := fchmodat2(dirfd, path, mode, flags) 255 if err == ENOSYS { 256 // fchmodat2 isn't available. If the flags are known to be valid, 257 // return EOPNOTSUPP to indicate that fchmodat doesn't support them. 258 if flags&^(_AT_SYMLINK_NOFOLLOW|_AT_EMPTY_PATH) != 0 { 259 return EINVAL 260 } else if flags&(_AT_SYMLINK_NOFOLLOW|_AT_EMPTY_PATH) != 0 { 261 return EOPNOTSUPP 262 } 263 } 264 return err 265 } 266 return fchmodat(dirfd, path, mode) 267} 268 269//sys linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) 270 271func Link(oldpath string, newpath string) (err error) { 272 return linkat(_AT_FDCWD, oldpath, _AT_FDCWD, newpath, 0) 273} 274 275func Mkdir(path string, mode uint32) (err error) { 276 return Mkdirat(_AT_FDCWD, path, mode) 277} 278 279func Mknod(path string, mode uint32, dev int) (err error) { 280 return Mknodat(_AT_FDCWD, path, mode, dev) 281} 282 283func Open(path string, mode int, perm uint32) (fd int, err error) { 284 return openat(_AT_FDCWD, path, mode|O_LARGEFILE, perm) 285} 286 287//sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) 288 289func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { 290 return openat(dirfd, path, flags|O_LARGEFILE, mode) 291} 292 293func Pipe(p []int) error { 294 return Pipe2(p, 0) 295} 296 297//sysnb pipe2(p *[2]_C_int, flags int) (err error) 298 299func Pipe2(p []int, flags int) error { 300 if len(p) != 2 { 301 return EINVAL 302 } 303 var pp [2]_C_int 304 err := pipe2(&pp, flags) 305 if err == nil { 306 p[0] = int(pp[0]) 307 p[1] = int(pp[1]) 308 } 309 return err 310} 311 312//sys readlinkat(dirfd int, path string, buf []byte) (n int, err error) 313 314func Readlink(path string, buf []byte) (n int, err error) { 315 return readlinkat(_AT_FDCWD, path, buf) 316} 317 318func Rename(oldpath string, newpath string) (err error) { 319 return Renameat(_AT_FDCWD, oldpath, _AT_FDCWD, newpath) 320} 321 322func Rmdir(path string) error { 323 return unlinkat(_AT_FDCWD, path, _AT_REMOVEDIR) 324} 325 326//sys symlinkat(oldpath string, newdirfd int, newpath string) (err error) 327 328func Symlink(oldpath string, newpath string) (err error) { 329 return symlinkat(oldpath, _AT_FDCWD, newpath) 330} 331 332func Unlink(path string) error { 333 return unlinkat(_AT_FDCWD, path, 0) 334} 335 336//sys unlinkat(dirfd int, path string, flags int) (err error) 337 338func Unlinkat(dirfd int, path string) error { 339 return unlinkat(dirfd, path, 0) 340} 341 342func Utimes(path string, tv []Timeval) (err error) { 343 if len(tv) != 2 { 344 return EINVAL 345 } 346 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 347} 348 349//sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error) 350 351func UtimesNano(path string, ts []Timespec) (err error) { 352 if len(ts) != 2 { 353 return EINVAL 354 } 355 return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) 356} 357 358func Futimesat(dirfd int, path string, tv []Timeval) (err error) { 359 if len(tv) != 2 { 360 return EINVAL 361 } 362 return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) 363} 364 365func Futimes(fd int, tv []Timeval) (err error) { 366 // Believe it or not, this is the best we can do on Linux 367 // (and is what glibc does). 368 return Utimes("/proc/self/fd/"+itoa.Itoa(fd), tv) 369} 370 371const ImplementsGetwd = true 372 373//sys Getcwd(buf []byte) (n int, err error) 374 375func Getwd() (wd string, err error) { 376 var buf [PathMax]byte 377 n, err := Getcwd(buf[0:]) 378 if err != nil { 379 return "", err 380 } 381 // Getcwd returns the number of bytes written to buf, including the NUL. 382 if n < 1 || n > len(buf) || buf[n-1] != 0 { 383 return "", EINVAL 384 } 385 // In some cases, Linux can return a path that starts with the 386 // "(unreachable)" prefix, which can potentially be a valid relative 387 // path. To work around that, return ENOENT if path is not absolute. 388 if buf[0] != '/' { 389 return "", ENOENT 390 } 391 392 return string(buf[0 : n-1]), nil 393} 394 395func Getgroups() (gids []int, err error) { 396 n, err := getgroups(0, nil) 397 if err != nil { 398 return nil, err 399 } 400 if n == 0 { 401 return nil, nil 402 } 403 404 // Sanity check group count. Max is 1<<16 on Linux. 405 if n < 0 || n > 1<<20 { 406 return nil, EINVAL 407 } 408 409 a := make([]_Gid_t, n) 410 n, err = getgroups(n, &a[0]) 411 if err != nil { 412 return nil, err 413 } 414 gids = make([]int, n) 415 for i, v := range a[0:n] { 416 gids[i] = int(v) 417 } 418 return 419} 420 421var cgo_libc_setgroups unsafe.Pointer // non-nil if cgo linked. 422 423func Setgroups(gids []int) (err error) { 424 n := uintptr(len(gids)) 425 if n == 0 { 426 if cgo_libc_setgroups == nil { 427 if _, _, e1 := AllThreadsSyscall(_SYS_setgroups, 0, 0, 0); e1 != 0 { 428 err = errnoErr(e1) 429 } 430 return 431 } 432 if ret := cgocaller(cgo_libc_setgroups, 0, 0); ret != 0 { 433 err = errnoErr(Errno(ret)) 434 } 435 return 436 } 437 438 a := make([]_Gid_t, len(gids)) 439 for i, v := range gids { 440 a[i] = _Gid_t(v) 441 } 442 if cgo_libc_setgroups == nil { 443 if _, _, e1 := AllThreadsSyscall(_SYS_setgroups, n, uintptr(unsafe.Pointer(&a[0])), 0); e1 != 0 { 444 err = errnoErr(e1) 445 } 446 return 447 } 448 if ret := cgocaller(cgo_libc_setgroups, n, uintptr(unsafe.Pointer(&a[0]))); ret != 0 { 449 err = errnoErr(Errno(ret)) 450 } 451 return 452} 453 454type WaitStatus uint32 455 456// Wait status is 7 bits at bottom, either 0 (exited), 457// 0x7F (stopped), or a signal number that caused an exit. 458// The 0x80 bit is whether there was a core dump. 459// An extra number (exit code, signal causing a stop) 460// is in the high bits. At least that's the idea. 461// There are various irregularities. For example, the 462// "continued" status is 0xFFFF, distinguishing itself 463// from stopped via the core dump bit. 464 465const ( 466 mask = 0x7F 467 core = 0x80 468 exited = 0x00 469 stopped = 0x7F 470 shift = 8 471) 472 473func (w WaitStatus) Exited() bool { return w&mask == exited } 474 475func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } 476 477func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } 478 479func (w WaitStatus) Continued() bool { return w == 0xFFFF } 480 481func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } 482 483func (w WaitStatus) ExitStatus() int { 484 if !w.Exited() { 485 return -1 486 } 487 return int(w>>shift) & 0xFF 488} 489 490func (w WaitStatus) Signal() Signal { 491 if !w.Signaled() { 492 return -1 493 } 494 return Signal(w & mask) 495} 496 497func (w WaitStatus) StopSignal() Signal { 498 if !w.Stopped() { 499 return -1 500 } 501 return Signal(w>>shift) & 0xFF 502} 503 504func (w WaitStatus) TrapCause() int { 505 if w.StopSignal() != SIGTRAP { 506 return -1 507 } 508 return int(w>>shift) >> 8 509} 510 511//sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) 512 513func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { 514 var status _C_int 515 wpid, err = wait4(pid, &status, options, rusage) 516 if wstatus != nil { 517 *wstatus = WaitStatus(status) 518 } 519 return 520} 521 522func Mkfifo(path string, mode uint32) (err error) { 523 return Mknod(path, mode|S_IFIFO, 0) 524} 525 526func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { 527 if sa.Port < 0 || sa.Port > 0xFFFF { 528 return nil, 0, EINVAL 529 } 530 sa.raw.Family = AF_INET 531 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 532 p[0] = byte(sa.Port >> 8) 533 p[1] = byte(sa.Port) 534 sa.raw.Addr = sa.Addr 535 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil 536} 537 538func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { 539 if sa.Port < 0 || sa.Port > 0xFFFF { 540 return nil, 0, EINVAL 541 } 542 sa.raw.Family = AF_INET6 543 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) 544 p[0] = byte(sa.Port >> 8) 545 p[1] = byte(sa.Port) 546 sa.raw.Scope_id = sa.ZoneId 547 sa.raw.Addr = sa.Addr 548 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil 549} 550 551func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { 552 name := sa.Name 553 n := len(name) 554 if n > len(sa.raw.Path) { 555 return nil, 0, EINVAL 556 } 557 if n == len(sa.raw.Path) && name[0] != '@' { 558 return nil, 0, EINVAL 559 } 560 sa.raw.Family = AF_UNIX 561 for i := 0; i < n; i++ { 562 sa.raw.Path[i] = int8(name[i]) 563 } 564 // length is family (uint16), name, NUL. 565 sl := _Socklen(2) 566 if n > 0 { 567 sl += _Socklen(n) + 1 568 } 569 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) { 570 // Check sl > 3 so we don't change unnamed socket behavior. 571 sa.raw.Path[0] = 0 572 // Don't count trailing NUL for abstract address. 573 sl-- 574 } 575 576 return unsafe.Pointer(&sa.raw), sl, nil 577} 578 579type SockaddrLinklayer struct { 580 Protocol uint16 581 Ifindex int 582 Hatype uint16 583 Pkttype uint8 584 Halen uint8 585 Addr [8]byte 586 raw RawSockaddrLinklayer 587} 588 589func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { 590 if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { 591 return nil, 0, EINVAL 592 } 593 sa.raw.Family = AF_PACKET 594 sa.raw.Protocol = sa.Protocol 595 sa.raw.Ifindex = int32(sa.Ifindex) 596 sa.raw.Hatype = sa.Hatype 597 sa.raw.Pkttype = sa.Pkttype 598 sa.raw.Halen = sa.Halen 599 sa.raw.Addr = sa.Addr 600 return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil 601} 602 603type SockaddrNetlink struct { 604 Family uint16 605 Pad uint16 606 Pid uint32 607 Groups uint32 608 raw RawSockaddrNetlink 609} 610 611func (sa *SockaddrNetlink) sockaddr() (unsafe.Pointer, _Socklen, error) { 612 sa.raw.Family = AF_NETLINK 613 sa.raw.Pad = sa.Pad 614 sa.raw.Pid = sa.Pid 615 sa.raw.Groups = sa.Groups 616 return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil 617} 618 619func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { 620 switch rsa.Addr.Family { 621 case AF_NETLINK: 622 pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa)) 623 sa := new(SockaddrNetlink) 624 sa.Family = pp.Family 625 sa.Pad = pp.Pad 626 sa.Pid = pp.Pid 627 sa.Groups = pp.Groups 628 return sa, nil 629 630 case AF_PACKET: 631 pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa)) 632 sa := new(SockaddrLinklayer) 633 sa.Protocol = pp.Protocol 634 sa.Ifindex = int(pp.Ifindex) 635 sa.Hatype = pp.Hatype 636 sa.Pkttype = pp.Pkttype 637 sa.Halen = pp.Halen 638 sa.Addr = pp.Addr 639 return sa, nil 640 641 case AF_UNIX: 642 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) 643 sa := new(SockaddrUnix) 644 if pp.Path[0] == 0 { 645 // "Abstract" Unix domain socket. 646 // Rewrite leading NUL as @ for textual display. 647 // (This is the standard convention.) 648 // Not friendly to overwrite in place, 649 // but the callers below don't care. 650 pp.Path[0] = '@' 651 } 652 653 // Assume path ends at NUL. 654 // This is not technically the Linux semantics for 655 // abstract Unix domain sockets--they are supposed 656 // to be uninterpreted fixed-size binary blobs--but 657 // everyone uses this convention. 658 n := 0 659 for n < len(pp.Path) && pp.Path[n] != 0 { 660 n++ 661 } 662 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n)) 663 return sa, nil 664 665 case AF_INET: 666 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) 667 sa := new(SockaddrInet4) 668 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 669 sa.Port = int(p[0])<<8 + int(p[1]) 670 sa.Addr = pp.Addr 671 return sa, nil 672 673 case AF_INET6: 674 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) 675 sa := new(SockaddrInet6) 676 p := (*[2]byte)(unsafe.Pointer(&pp.Port)) 677 sa.Port = int(p[0])<<8 + int(p[1]) 678 sa.ZoneId = pp.Scope_id 679 sa.Addr = pp.Addr 680 return sa, nil 681 } 682 return nil, EAFNOSUPPORT 683} 684 685func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { 686 var rsa RawSockaddrAny 687 var len _Socklen = SizeofSockaddrAny 688 nfd, err = accept4(fd, &rsa, &len, flags) 689 if err != nil { 690 return 691 } 692 if len > SizeofSockaddrAny { 693 panic("RawSockaddrAny too small") 694 } 695 sa, err = anyToSockaddr(&rsa) 696 if err != nil { 697 Close(nfd) 698 nfd = 0 699 } 700 return 701} 702 703func Getsockname(fd int) (sa Sockaddr, err error) { 704 var rsa RawSockaddrAny 705 var len _Socklen = SizeofSockaddrAny 706 if err = getsockname(fd, &rsa, &len); err != nil { 707 return 708 } 709 return anyToSockaddr(&rsa) 710} 711 712func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { 713 vallen := _Socklen(4) 714 err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) 715 return value, err 716} 717 718func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { 719 var value IPMreq 720 vallen := _Socklen(SizeofIPMreq) 721 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 722 return &value, err 723} 724 725func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) { 726 var value IPMreqn 727 vallen := _Socklen(SizeofIPMreqn) 728 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 729 return &value, err 730} 731 732func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { 733 var value IPv6Mreq 734 vallen := _Socklen(SizeofIPv6Mreq) 735 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 736 return &value, err 737} 738 739func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { 740 var value IPv6MTUInfo 741 vallen := _Socklen(SizeofIPv6MTUInfo) 742 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 743 return &value, err 744} 745 746func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { 747 var value ICMPv6Filter 748 vallen := _Socklen(SizeofICMPv6Filter) 749 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 750 return &value, err 751} 752 753func GetsockoptUcred(fd, level, opt int) (*Ucred, error) { 754 var value Ucred 755 vallen := _Socklen(SizeofUcred) 756 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 757 return &value, err 758} 759 760func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { 761 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) 762} 763 764func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { 765 var msg Msghdr 766 msg.Name = (*byte)(unsafe.Pointer(rsa)) 767 msg.Namelen = uint32(SizeofSockaddrAny) 768 var iov Iovec 769 if len(p) > 0 { 770 iov.Base = &p[0] 771 iov.SetLen(len(p)) 772 } 773 var dummy byte 774 if len(oob) > 0 { 775 if len(p) == 0 { 776 var sockType int 777 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) 778 if err != nil { 779 return 780 } 781 // receive at least one normal byte 782 if sockType != SOCK_DGRAM { 783 iov.Base = &dummy 784 iov.SetLen(1) 785 } 786 } 787 msg.Control = &oob[0] 788 msg.SetControllen(len(oob)) 789 } 790 msg.Iov = &iov 791 msg.Iovlen = 1 792 if n, err = recvmsg(fd, &msg, flags); err != nil { 793 return 794 } 795 oobn = int(msg.Controllen) 796 recvflags = int(msg.Flags) 797 return 798} 799 800func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { 801 var msg Msghdr 802 msg.Name = (*byte)(ptr) 803 msg.Namelen = uint32(salen) 804 var iov Iovec 805 if len(p) > 0 { 806 iov.Base = &p[0] 807 iov.SetLen(len(p)) 808 } 809 var dummy byte 810 if len(oob) > 0 { 811 if len(p) == 0 { 812 var sockType int 813 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) 814 if err != nil { 815 return 0, err 816 } 817 // send at least one normal byte 818 if sockType != SOCK_DGRAM { 819 iov.Base = &dummy 820 iov.SetLen(1) 821 } 822 } 823 msg.Control = &oob[0] 824 msg.SetControllen(len(oob)) 825 } 826 msg.Iov = &iov 827 msg.Iovlen = 1 828 if n, err = sendmsg(fd, &msg, flags); err != nil { 829 return 0, err 830 } 831 if len(oob) > 0 && len(p) == 0 { 832 n = 0 833 } 834 return n, nil 835} 836 837// BindToDevice binds the socket associated with fd to device. 838func BindToDevice(fd int, device string) (err error) { 839 return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device) 840} 841 842//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) 843//sys ptracePtr(request int, pid int, addr uintptr, data unsafe.Pointer) (err error) = SYS_PTRACE 844 845func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) { 846 // The peek requests are machine-size oriented, so we wrap it 847 // to retrieve arbitrary-length data. 848 849 // The ptrace syscall differs from glibc's ptrace. 850 // Peeks returns the word in *data, not as the return value. 851 852 var buf [sizeofPtr]byte 853 854 // Leading edge. PEEKTEXT/PEEKDATA don't require aligned 855 // access (PEEKUSER warns that it might), but if we don't 856 // align our reads, we might straddle an unmapped page 857 // boundary and not get the bytes leading up to the page 858 // boundary. 859 n := 0 860 if addr%sizeofPtr != 0 { 861 err = ptracePtr(req, pid, addr-addr%sizeofPtr, unsafe.Pointer(&buf[0])) 862 if err != nil { 863 return 0, err 864 } 865 n += copy(out, buf[addr%sizeofPtr:]) 866 out = out[n:] 867 } 868 869 // Remainder. 870 for len(out) > 0 { 871 // We use an internal buffer to guarantee alignment. 872 // It's not documented if this is necessary, but we're paranoid. 873 err = ptracePtr(req, pid, addr+uintptr(n), unsafe.Pointer(&buf[0])) 874 if err != nil { 875 return n, err 876 } 877 copied := copy(out, buf[0:]) 878 n += copied 879 out = out[copied:] 880 } 881 882 return n, nil 883} 884 885func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) { 886 return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out) 887} 888 889func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { 890 return ptracePeek(PTRACE_PEEKDATA, pid, addr, out) 891} 892 893func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) { 894 // As for ptracePeek, we need to align our accesses to deal 895 // with the possibility of straddling an invalid page. 896 897 // Leading edge. 898 n := 0 899 if addr%sizeofPtr != 0 { 900 var buf [sizeofPtr]byte 901 err = ptracePtr(peekReq, pid, addr-addr%sizeofPtr, unsafe.Pointer(&buf[0])) 902 if err != nil { 903 return 0, err 904 } 905 n += copy(buf[addr%sizeofPtr:], data) 906 word := *((*uintptr)(unsafe.Pointer(&buf[0]))) 907 err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word) 908 if err != nil { 909 return 0, err 910 } 911 data = data[n:] 912 } 913 914 // Interior. 915 for len(data) > sizeofPtr { 916 word := *((*uintptr)(unsafe.Pointer(&data[0]))) 917 err = ptrace(pokeReq, pid, addr+uintptr(n), word) 918 if err != nil { 919 return n, err 920 } 921 n += sizeofPtr 922 data = data[sizeofPtr:] 923 } 924 925 // Trailing edge. 926 if len(data) > 0 { 927 var buf [sizeofPtr]byte 928 err = ptracePtr(peekReq, pid, addr+uintptr(n), unsafe.Pointer(&buf[0])) 929 if err != nil { 930 return n, err 931 } 932 copy(buf[0:], data) 933 word := *((*uintptr)(unsafe.Pointer(&buf[0]))) 934 err = ptrace(pokeReq, pid, addr+uintptr(n), word) 935 if err != nil { 936 return n, err 937 } 938 n += len(data) 939 } 940 941 return n, nil 942} 943 944func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) { 945 return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data) 946} 947 948func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) { 949 return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data) 950} 951 952const ( 953 _NT_PRSTATUS = 1 954) 955 956func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { 957 var iov Iovec 958 iov.Base = (*byte)(unsafe.Pointer(regsout)) 959 iov.SetLen(int(unsafe.Sizeof(*regsout))) 960 return ptracePtr(PTRACE_GETREGSET, pid, uintptr(_NT_PRSTATUS), unsafe.Pointer(&iov)) 961} 962 963func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { 964 var iov Iovec 965 iov.Base = (*byte)(unsafe.Pointer(regs)) 966 iov.SetLen(int(unsafe.Sizeof(*regs))) 967 return ptracePtr(PTRACE_SETREGSET, pid, uintptr(_NT_PRSTATUS), unsafe.Pointer(&iov)) 968} 969 970func PtraceSetOptions(pid int, options int) (err error) { 971 return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options)) 972} 973 974func PtraceGetEventMsg(pid int) (msg uint, err error) { 975 var data _C_long 976 err = ptracePtr(PTRACE_GETEVENTMSG, pid, 0, unsafe.Pointer(&data)) 977 msg = uint(data) 978 return 979} 980 981func PtraceCont(pid int, signal int) (err error) { 982 return ptrace(PTRACE_CONT, pid, 0, uintptr(signal)) 983} 984 985func PtraceSyscall(pid int, signal int) (err error) { 986 return ptrace(PTRACE_SYSCALL, pid, 0, uintptr(signal)) 987} 988 989func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } 990 991func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } 992 993func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) } 994 995//sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) 996 997func Reboot(cmd int) (err error) { 998 return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "") 999} 1000 1001func ReadDirent(fd int, buf []byte) (n int, err error) { 1002 return Getdents(fd, buf) 1003} 1004 1005func direntIno(buf []byte) (uint64, bool) { 1006 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) 1007} 1008 1009func direntReclen(buf []byte) (uint64, bool) { 1010 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) 1011} 1012 1013func direntNamlen(buf []byte) (uint64, bool) { 1014 reclen, ok := direntReclen(buf) 1015 if !ok { 1016 return 0, false 1017 } 1018 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true 1019} 1020 1021//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) 1022 1023func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { 1024 // Certain file systems get rather angry and EINVAL if you give 1025 // them an empty string of data, rather than NULL. 1026 if data == "" { 1027 return mount(source, target, fstype, flags, nil) 1028 } 1029 datap, err := BytePtrFromString(data) 1030 if err != nil { 1031 return err 1032 } 1033 return mount(source, target, fstype, flags, datap) 1034} 1035 1036// Sendto 1037// Recvfrom 1038// Socketpair 1039 1040/* 1041 * Direct access 1042 */ 1043//sys Acct(path string) (err error) 1044//sys Adjtimex(buf *Timex) (state int, err error) 1045//sys Chdir(path string) (err error) 1046//sys Chroot(path string) (err error) 1047//sys Close(fd int) (err error) 1048//sys Dup(oldfd int) (fd int, err error) 1049//sys Dup3(oldfd int, newfd int, flags int) (err error) 1050//sysnb EpollCreate1(flag int) (fd int, err error) 1051//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) 1052//sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) 1053//sys Fchdir(fd int) (err error) 1054//sys Fchmod(fd int, mode uint32) (err error) 1055//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) 1056//sys fcntl(fd int, cmd int, arg int) (val int, err error) 1057//sys Fdatasync(fd int) (err error) 1058//sys Flock(fd int, how int) (err error) 1059//sys Fsync(fd int) (err error) 1060//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 1061//sysnb Getpgid(pid int) (pgid int, err error) 1062 1063func Getpgrp() (pid int) { 1064 pid, _ = Getpgid(0) 1065 return 1066} 1067 1068//sysnb Getpid() (pid int) 1069//sysnb Getppid() (ppid int) 1070//sys Getpriority(which int, who int) (prio int, err error) 1071//sysnb Getrusage(who int, rusage *Rusage) (err error) 1072//sysnb Gettid() (tid int) 1073//sys Getxattr(path string, attr string, dest []byte) (sz int, err error) 1074//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) 1075//sysnb InotifyInit1(flags int) (fd int, err error) 1076//sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) 1077//sysnb Kill(pid int, sig Signal) (err error) 1078//sys Klogctl(typ int, buf []byte) (n int, err error) = SYS_SYSLOG 1079//sys Listxattr(path string, dest []byte) (sz int, err error) 1080//sys Mkdirat(dirfd int, path string, mode uint32) (err error) 1081//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) 1082//sys Nanosleep(time *Timespec, leftover *Timespec) (err error) 1083//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT 1084//sysnb prlimit1(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 1085//sys read(fd int, p []byte) (n int, err error) 1086//sys Removexattr(path string, attr string) (err error) 1087//sys Setdomainname(p []byte) (err error) 1088//sys Sethostname(p []byte) (err error) 1089//sysnb Setpgid(pid int, pgid int) (err error) 1090//sysnb Setsid() (pid int, err error) 1091//sysnb Settimeofday(tv *Timeval) (err error) 1092 1093// Provided by runtime.syscall_runtime_doAllThreadsSyscall which stops the 1094// world and invokes the syscall on each OS thread. Once this function returns, 1095// all threads are in sync. 1096// 1097//go:uintptrescapes 1098func runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) 1099 1100// AllThreadsSyscall performs a syscall on each OS thread of the Go 1101// runtime. It first invokes the syscall on one thread. Should that 1102// invocation fail, it returns immediately with the error status. 1103// Otherwise, it invokes the syscall on all of the remaining threads 1104// in parallel. It will terminate the program if it observes any 1105// invoked syscall's return value differs from that of the first 1106// invocation. 1107// 1108// AllThreadsSyscall is intended for emulating simultaneous 1109// process-wide state changes that require consistently modifying 1110// per-thread state of the Go runtime. 1111// 1112// AllThreadsSyscall is unaware of any threads that are launched 1113// explicitly by cgo linked code, so the function always returns 1114// [ENOTSUP] in binaries that use cgo. 1115// 1116//go:uintptrescapes 1117func AllThreadsSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 1118 if cgo_libc_setegid != nil { 1119 return minus1, minus1, ENOTSUP 1120 } 1121 r1, r2, errno := runtime_doAllThreadsSyscall(trap, a1, a2, a3, 0, 0, 0) 1122 return r1, r2, Errno(errno) 1123} 1124 1125// AllThreadsSyscall6 is like [AllThreadsSyscall], but extended to six 1126// arguments. 1127// 1128//go:uintptrescapes 1129func AllThreadsSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 1130 if cgo_libc_setegid != nil { 1131 return minus1, minus1, ENOTSUP 1132 } 1133 r1, r2, errno := runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6) 1134 return r1, r2, Errno(errno) 1135} 1136 1137// linked by runtime.cgocall.go 1138// 1139//go:uintptrescapes 1140func cgocaller(unsafe.Pointer, ...uintptr) uintptr 1141 1142var cgo_libc_setegid unsafe.Pointer // non-nil if cgo linked. 1143 1144const minus1 = ^uintptr(0) 1145 1146func Setegid(egid int) (err error) { 1147 if cgo_libc_setegid == nil { 1148 if _, _, e1 := AllThreadsSyscall(SYS_SETRESGID, minus1, uintptr(egid), minus1); e1 != 0 { 1149 err = errnoErr(e1) 1150 } 1151 } else if ret := cgocaller(cgo_libc_setegid, uintptr(egid)); ret != 0 { 1152 err = errnoErr(Errno(ret)) 1153 } 1154 return 1155} 1156 1157var cgo_libc_seteuid unsafe.Pointer // non-nil if cgo linked. 1158 1159func Seteuid(euid int) (err error) { 1160 if cgo_libc_seteuid == nil { 1161 if _, _, e1 := AllThreadsSyscall(SYS_SETRESUID, minus1, uintptr(euid), minus1); e1 != 0 { 1162 err = errnoErr(e1) 1163 } 1164 } else if ret := cgocaller(cgo_libc_seteuid, uintptr(euid)); ret != 0 { 1165 err = errnoErr(Errno(ret)) 1166 } 1167 return 1168} 1169 1170var cgo_libc_setgid unsafe.Pointer // non-nil if cgo linked. 1171 1172func Setgid(gid int) (err error) { 1173 if cgo_libc_setgid == nil { 1174 if _, _, e1 := AllThreadsSyscall(sys_SETGID, uintptr(gid), 0, 0); e1 != 0 { 1175 err = errnoErr(e1) 1176 } 1177 } else if ret := cgocaller(cgo_libc_setgid, uintptr(gid)); ret != 0 { 1178 err = errnoErr(Errno(ret)) 1179 } 1180 return 1181} 1182 1183var cgo_libc_setregid unsafe.Pointer // non-nil if cgo linked. 1184 1185func Setregid(rgid, egid int) (err error) { 1186 if cgo_libc_setregid == nil { 1187 if _, _, e1 := AllThreadsSyscall(sys_SETREGID, uintptr(rgid), uintptr(egid), 0); e1 != 0 { 1188 err = errnoErr(e1) 1189 } 1190 } else if ret := cgocaller(cgo_libc_setregid, uintptr(rgid), uintptr(egid)); ret != 0 { 1191 err = errnoErr(Errno(ret)) 1192 } 1193 return 1194} 1195 1196var cgo_libc_setresgid unsafe.Pointer // non-nil if cgo linked. 1197 1198func Setresgid(rgid, egid, sgid int) (err error) { 1199 if cgo_libc_setresgid == nil { 1200 if _, _, e1 := AllThreadsSyscall(sys_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)); e1 != 0 { 1201 err = errnoErr(e1) 1202 } 1203 } else if ret := cgocaller(cgo_libc_setresgid, uintptr(rgid), uintptr(egid), uintptr(sgid)); ret != 0 { 1204 err = errnoErr(Errno(ret)) 1205 } 1206 return 1207} 1208 1209var cgo_libc_setresuid unsafe.Pointer // non-nil if cgo linked. 1210 1211func Setresuid(ruid, euid, suid int) (err error) { 1212 if cgo_libc_setresuid == nil { 1213 if _, _, e1 := AllThreadsSyscall(sys_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)); e1 != 0 { 1214 err = errnoErr(e1) 1215 } 1216 } else if ret := cgocaller(cgo_libc_setresuid, uintptr(ruid), uintptr(euid), uintptr(suid)); ret != 0 { 1217 err = errnoErr(Errno(ret)) 1218 } 1219 return 1220} 1221 1222var cgo_libc_setreuid unsafe.Pointer // non-nil if cgo linked. 1223 1224func Setreuid(ruid, euid int) (err error) { 1225 if cgo_libc_setreuid == nil { 1226 if _, _, e1 := AllThreadsSyscall(sys_SETREUID, uintptr(ruid), uintptr(euid), 0); e1 != 0 { 1227 err = errnoErr(e1) 1228 } 1229 } else if ret := cgocaller(cgo_libc_setreuid, uintptr(ruid), uintptr(euid)); ret != 0 { 1230 err = errnoErr(Errno(ret)) 1231 } 1232 return 1233} 1234 1235var cgo_libc_setuid unsafe.Pointer // non-nil if cgo linked. 1236 1237func Setuid(uid int) (err error) { 1238 if cgo_libc_setuid == nil { 1239 if _, _, e1 := AllThreadsSyscall(sys_SETUID, uintptr(uid), 0, 0); e1 != 0 { 1240 err = errnoErr(e1) 1241 } 1242 } else if ret := cgocaller(cgo_libc_setuid, uintptr(uid)); ret != 0 { 1243 err = errnoErr(Errno(ret)) 1244 } 1245 return 1246} 1247 1248//sys Setpriority(which int, who int, prio int) (err error) 1249//sys Setxattr(path string, attr string, data []byte, flags int) (err error) 1250//sys Sync() 1251//sysnb Sysinfo(info *Sysinfo_t) (err error) 1252//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) 1253//sysnb Tgkill(tgid int, tid int, sig Signal) (err error) 1254//sysnb Times(tms *Tms) (ticks uintptr, err error) 1255//sysnb Umask(mask int) (oldmask int) 1256//sysnb Uname(buf *Utsname) (err error) 1257//sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2 1258//sys Unshare(flags int) (err error) 1259//sys write(fd int, p []byte) (n int, err error) 1260//sys exitThread(code int) (err error) = SYS_EXIT 1261//sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ 1262 1263// mmap varies by architecture; see syscall_linux_*.go. 1264//sys munmap(addr uintptr, length uintptr) (err error) 1265 1266var mapper = &mmapper{ 1267 active: make(map[*byte][]byte), 1268 mmap: mmap, 1269 munmap: munmap, 1270} 1271 1272func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 1273 return mapper.Mmap(fd, offset, length, prot, flags) 1274} 1275 1276func Munmap(b []byte) (err error) { 1277 return mapper.Munmap(b) 1278} 1279 1280//sys Madvise(b []byte, advice int) (err error) 1281//sys Mprotect(b []byte, prot int) (err error) 1282//sys Mlock(b []byte) (err error) 1283//sys Munlock(b []byte) (err error) 1284//sys Mlockall(flags int) (err error) 1285//sys Munlockall() (err error) 1286 1287// prlimit changes a resource limit. We use a single definition so that 1288// we can tell StartProcess to not restore the original NOFILE limit. 1289// 1290// golang.org/x/sys linknames prlimit. 1291// Do not remove or change the type signature. 1292// 1293//go:linkname prlimit 1294func prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { 1295 err = prlimit1(pid, resource, newlimit, old) 1296 if err == nil && newlimit != nil && resource == RLIMIT_NOFILE && (pid == 0 || pid == Getpid()) { 1297 origRlimitNofile.Store(nil) 1298 } 1299 return err 1300} 1301