Source file
src/syscall/syscall_linux.go
1
2
3
4
5
6
7
8
9
10
11
12 package syscall
13
14 import (
15 "internal/itoa"
16 runtimesyscall "internal/runtime/syscall"
17 "runtime"
18 "slices"
19 "unsafe"
20 )
21
22
23
24
25
26
27
28
29
30 func runtime_entersyscall()
31
32
33 func runtime_exitsyscall()
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
56 return RawSyscall6(trap, a1, a2, a3, 0, 0, 0)
57 }
58
59
60
61
62
63 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
64 var errno uintptr
65 r1, r2, errno = runtimesyscall.Syscall6(trap, a1, a2, a3, a4, a5, a6)
66 err = Errno(errno)
67 return
68 }
69
70
71
72
73 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
74 runtime_entersyscall()
75
76
77
78
79
80
81
82
83
84
85
86
87 r1, r2, err = RawSyscall6(trap, a1, a2, a3, 0, 0, 0)
88 runtime_exitsyscall()
89 return
90 }
91
92
93
94
95 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
96 runtime_entersyscall()
97 r1, r2, err = RawSyscall6(trap, a1, a2, a3, a4, a5, a6)
98 runtime_exitsyscall()
99 return
100 }
101
102 func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr)
103 func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1 uintptr, err Errno)
104
105
108
109 func Access(path string, mode uint32) (err error) {
110 return Faccessat(_AT_FDCWD, path, mode, 0)
111 }
112
113 func Chmod(path string, mode uint32) (err error) {
114 return Fchmodat(_AT_FDCWD, path, mode, 0)
115 }
116
117 func Chown(path string, uid int, gid int) (err error) {
118 return Fchownat(_AT_FDCWD, path, uid, gid, 0)
119 }
120
121 func Creat(path string, mode uint32) (fd int, err error) {
122 return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
123 }
124
125 func EpollCreate(size int) (fd int, err error) {
126 if size <= 0 {
127 return -1, EINVAL
128 }
129 return EpollCreate1(0)
130 }
131
132 func isGroupMember(gid int) bool {
133 groups, err := Getgroups()
134 if err != nil {
135 return false
136 }
137
138 return slices.Contains(groups, gid)
139 }
140
141 func isCapDacOverrideSet() bool {
142 const _CAP_DAC_OVERRIDE = 1
143 var c caps
144 c.hdr.version = _LINUX_CAPABILITY_VERSION_3
145
146 _, _, err := RawSyscall(SYS_CAPGET, uintptr(unsafe.Pointer(&c.hdr)), uintptr(unsafe.Pointer(&c.data[0])), 0)
147
148 return err == 0 && c.data[0].effective&capToMask(_CAP_DAC_OVERRIDE) != 0
149 }
150
151
152
153
154 func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
155 if flags == 0 {
156 return faccessat(dirfd, path, mode)
157 }
158
159
160
161
162
163
164
165
166 if runtime.GOOS != "android" {
167 if err := faccessat2(dirfd, path, mode, flags); err != ENOSYS && err != EPERM {
168 return err
169 }
170 }
171
172
173
174
175
176
177
178 if flags & ^(_AT_SYMLINK_NOFOLLOW|_AT_EACCESS) != 0 {
179 return EINVAL
180 }
181
182 var st Stat_t
183 if err := fstatat(dirfd, path, &st, flags&_AT_SYMLINK_NOFOLLOW); err != nil {
184 return err
185 }
186
187 mode &= 7
188 if mode == 0 {
189 return nil
190 }
191
192
193 var uid int
194 if flags&_AT_EACCESS != 0 {
195 uid = Geteuid()
196 if uid != 0 && isCapDacOverrideSet() {
197
198
199
200 uid = 0
201 }
202 } else {
203 uid = Getuid()
204 }
205
206 if uid == 0 {
207 if mode&1 == 0 {
208
209 return nil
210 }
211 if st.Mode&0111 != 0 {
212
213 return nil
214 }
215 return EACCES
216 }
217
218 var fmode uint32
219 if uint32(uid) == st.Uid {
220 fmode = (st.Mode >> 6) & 7
221 } else {
222 var gid int
223 if flags&_AT_EACCESS != 0 {
224 gid = Getegid()
225 } else {
226 gid = Getgid()
227 }
228
229 if uint32(gid) == st.Gid || isGroupMember(int(st.Gid)) {
230 fmode = (st.Mode >> 3) & 7
231 } else {
232 fmode = st.Mode & 7
233 }
234 }
235
236 if fmode&mode == mode {
237 return nil
238 }
239
240 return EACCES
241 }
242
243
244
245
246 func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
247
248
249 if flags != 0 {
250 err := fchmodat2(dirfd, path, mode, flags)
251 if err == ENOSYS {
252
253
254 if flags&^(_AT_SYMLINK_NOFOLLOW|_AT_EMPTY_PATH) != 0 {
255 return EINVAL
256 } else if flags&(_AT_SYMLINK_NOFOLLOW|_AT_EMPTY_PATH) != 0 {
257 return EOPNOTSUPP
258 }
259 }
260 return err
261 }
262 return fchmodat(dirfd, path, mode)
263 }
264
265
266
267 func Link(oldpath string, newpath string) (err error) {
268 return linkat(_AT_FDCWD, oldpath, _AT_FDCWD, newpath, 0)
269 }
270
271 func Mkdir(path string, mode uint32) (err error) {
272 return Mkdirat(_AT_FDCWD, path, mode)
273 }
274
275 func Mknod(path string, mode uint32, dev int) (err error) {
276 return Mknodat(_AT_FDCWD, path, mode, dev)
277 }
278
279 func Open(path string, mode int, perm uint32) (fd int, err error) {
280 return openat(_AT_FDCWD, path, mode|O_LARGEFILE, perm)
281 }
282
283
284
285 func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
286 return openat(dirfd, path, flags|O_LARGEFILE, mode)
287 }
288
289 func Pipe(p []int) error {
290 return Pipe2(p, 0)
291 }
292
293
294
295 func Pipe2(p []int, flags int) error {
296 if len(p) != 2 {
297 return EINVAL
298 }
299 var pp [2]_C_int
300 err := pipe2(&pp, flags)
301 if err == nil {
302 p[0] = int(pp[0])
303 p[1] = int(pp[1])
304 }
305 return err
306 }
307
308
309
310 func Readlink(path string, buf []byte) (n int, err error) {
311 return readlinkat(_AT_FDCWD, path, buf)
312 }
313
314 func Rename(oldpath string, newpath string) (err error) {
315 return Renameat(_AT_FDCWD, oldpath, _AT_FDCWD, newpath)
316 }
317
318 func Rmdir(path string) error {
319 return unlinkat(_AT_FDCWD, path, _AT_REMOVEDIR)
320 }
321
322
323
324 func Symlink(oldpath string, newpath string) (err error) {
325 return symlinkat(oldpath, _AT_FDCWD, newpath)
326 }
327
328 func Unlink(path string) error {
329 return unlinkat(_AT_FDCWD, path, 0)
330 }
331
332
333
334 func Unlinkat(dirfd int, path string) error {
335 return unlinkat(dirfd, path, 0)
336 }
337
338 func Utimes(path string, tv []Timeval) (err error) {
339 if len(tv) != 2 {
340 return EINVAL
341 }
342 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
343 }
344
345
346
347 func UtimesNano(path string, ts []Timespec) (err error) {
348 if len(ts) != 2 {
349 return EINVAL
350 }
351 return utimensat(_AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
352 }
353
354 func Futimesat(dirfd int, path string, tv []Timeval) (err error) {
355 if len(tv) != 2 {
356 return EINVAL
357 }
358 return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
359 }
360
361 func Futimes(fd int, tv []Timeval) (err error) {
362
363
364 return Utimes("/proc/self/fd/"+itoa.Itoa(fd), tv)
365 }
366
367 const ImplementsGetwd = true
368
369
370
371 func Getwd() (wd string, err error) {
372 var buf [PathMax]byte
373 n, err := Getcwd(buf[0:])
374 if err != nil {
375 return "", err
376 }
377
378 if n < 1 || n > len(buf) || buf[n-1] != 0 {
379 return "", EINVAL
380 }
381
382
383
384 if buf[0] != '/' {
385 return "", ENOENT
386 }
387
388 return string(buf[0 : n-1]), nil
389 }
390
391 func Getgroups() (gids []int, err error) {
392 n, err := getgroups(0, nil)
393 if err != nil {
394 return nil, err
395 }
396 if n == 0 {
397 return nil, nil
398 }
399
400
401 if n < 0 || n > 1<<20 {
402 return nil, EINVAL
403 }
404
405 a := make([]_Gid_t, n)
406 n, err = getgroups(n, &a[0])
407 if err != nil {
408 return nil, err
409 }
410 gids = make([]int, n)
411 for i, v := range a[0:n] {
412 gids[i] = int(v)
413 }
414 return
415 }
416
417 var cgo_libc_setgroups unsafe.Pointer
418
419 func Setgroups(gids []int) (err error) {
420 n := uintptr(len(gids))
421 if n == 0 {
422 if cgo_libc_setgroups == nil {
423 if _, _, e1 := AllThreadsSyscall(_SYS_setgroups, 0, 0, 0); e1 != 0 {
424 err = errnoErr(e1)
425 }
426 return
427 }
428 if ret := cgocaller(cgo_libc_setgroups, 0, 0); ret != 0 {
429 err = errnoErr(Errno(ret))
430 }
431 return
432 }
433
434 a := make([]_Gid_t, len(gids))
435 for i, v := range gids {
436 a[i] = _Gid_t(v)
437 }
438 if cgo_libc_setgroups == nil {
439 if _, _, e1 := AllThreadsSyscall(_SYS_setgroups, n, uintptr(unsafe.Pointer(&a[0])), 0); e1 != 0 {
440 err = errnoErr(e1)
441 }
442 return
443 }
444 if ret := cgocaller(cgo_libc_setgroups, n, uintptr(unsafe.Pointer(&a[0]))); ret != 0 {
445 err = errnoErr(Errno(ret))
446 }
447 return
448 }
449
450 type WaitStatus uint32
451
452
453
454
455
456
457
458
459
460
461 const (
462 mask = 0x7F
463 core = 0x80
464 exited = 0x00
465 stopped = 0x7F
466 shift = 8
467 )
468
469 func (w WaitStatus) Exited() bool { return w&mask == exited }
470
471 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
472
473 func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
474
475 func (w WaitStatus) Continued() bool { return w == 0xFFFF }
476
477 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
478
479 func (w WaitStatus) ExitStatus() int {
480 if !w.Exited() {
481 return -1
482 }
483 return int(w>>shift) & 0xFF
484 }
485
486 func (w WaitStatus) Signal() Signal {
487 if !w.Signaled() {
488 return -1
489 }
490 return Signal(w & mask)
491 }
492
493 func (w WaitStatus) StopSignal() Signal {
494 if !w.Stopped() {
495 return -1
496 }
497 return Signal(w>>shift) & 0xFF
498 }
499
500 func (w WaitStatus) TrapCause() int {
501 if w.StopSignal() != SIGTRAP {
502 return -1
503 }
504 return int(w>>shift) >> 8
505 }
506
507
508
509 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
510 var status _C_int
511 wpid, err = wait4(pid, &status, options, rusage)
512 if wstatus != nil {
513 *wstatus = WaitStatus(status)
514 }
515 return
516 }
517
518 func Mkfifo(path string, mode uint32) (err error) {
519 return Mknod(path, mode|S_IFIFO, 0)
520 }
521
522 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
523 if sa.Port < 0 || sa.Port > 0xFFFF {
524 return nil, 0, EINVAL
525 }
526 sa.raw.Family = AF_INET
527 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
528 p[0] = byte(sa.Port >> 8)
529 p[1] = byte(sa.Port)
530 sa.raw.Addr = sa.Addr
531 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
532 }
533
534 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
535 if sa.Port < 0 || sa.Port > 0xFFFF {
536 return nil, 0, EINVAL
537 }
538 sa.raw.Family = AF_INET6
539 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
540 p[0] = byte(sa.Port >> 8)
541 p[1] = byte(sa.Port)
542 sa.raw.Scope_id = sa.ZoneId
543 sa.raw.Addr = sa.Addr
544 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
545 }
546
547 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
548 name := sa.Name
549 n := len(name)
550 if n > len(sa.raw.Path) {
551 return nil, 0, EINVAL
552 }
553
554
555 isAbstract := n > 0 && (name[0] == '@' || name[0] == '\x00')
556
557
558
559 if n == len(sa.raw.Path) && !isAbstract {
560 return nil, 0, EINVAL
561 }
562 sa.raw.Family = AF_UNIX
563 for i := 0; i < n; i++ {
564 sa.raw.Path[i] = int8(name[i])
565 }
566
567
568 sl := _Socklen(2 + n)
569 if isAbstract {
570
571
572 sa.raw.Path[0] = 0
573 } else if n > 0 {
574
575 sl++
576 }
577
578 return unsafe.Pointer(&sa.raw), sl, nil
579 }
580
581 type SockaddrLinklayer struct {
582 Protocol uint16
583 Ifindex int
584 Hatype uint16
585 Pkttype uint8
586 Halen uint8
587 Addr [8]byte
588 raw RawSockaddrLinklayer
589 }
590
591 func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) {
592 if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
593 return nil, 0, EINVAL
594 }
595 sa.raw.Family = AF_PACKET
596 sa.raw.Protocol = sa.Protocol
597 sa.raw.Ifindex = int32(sa.Ifindex)
598 sa.raw.Hatype = sa.Hatype
599 sa.raw.Pkttype = sa.Pkttype
600 sa.raw.Halen = sa.Halen
601 sa.raw.Addr = sa.Addr
602 return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil
603 }
604
605 type SockaddrNetlink struct {
606 Family uint16
607 Pad uint16
608 Pid uint32
609 Groups uint32
610 raw RawSockaddrNetlink
611 }
612
613 func (sa *SockaddrNetlink) sockaddr() (unsafe.Pointer, _Socklen, error) {
614 sa.raw.Family = AF_NETLINK
615 sa.raw.Pad = sa.Pad
616 sa.raw.Pid = sa.Pid
617 sa.raw.Groups = sa.Groups
618 return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil
619 }
620
621 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
622 switch rsa.Addr.Family {
623 case AF_NETLINK:
624 pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
625 sa := new(SockaddrNetlink)
626 sa.Family = pp.Family
627 sa.Pad = pp.Pad
628 sa.Pid = pp.Pid
629 sa.Groups = pp.Groups
630 return sa, nil
631
632 case AF_PACKET:
633 pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))
634 sa := new(SockaddrLinklayer)
635 sa.Protocol = pp.Protocol
636 sa.Ifindex = int(pp.Ifindex)
637 sa.Hatype = pp.Hatype
638 sa.Pkttype = pp.Pkttype
639 sa.Halen = pp.Halen
640 sa.Addr = pp.Addr
641 return sa, nil
642
643 case AF_UNIX:
644 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
645 sa := new(SockaddrUnix)
646 if pp.Path[0] == 0 {
647
648
649
650
651
652 pp.Path[0] = '@'
653 }
654
655
656
657
658
659
660 n := 0
661 for n < len(pp.Path) && pp.Path[n] != 0 {
662 n++
663 }
664 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
665 return sa, nil
666
667 case AF_INET:
668 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
669 sa := new(SockaddrInet4)
670 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
671 sa.Port = int(p[0])<<8 + int(p[1])
672 sa.Addr = pp.Addr
673 return sa, nil
674
675 case AF_INET6:
676 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
677 sa := new(SockaddrInet6)
678 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
679 sa.Port = int(p[0])<<8 + int(p[1])
680 sa.ZoneId = pp.Scope_id
681 sa.Addr = pp.Addr
682 return sa, nil
683 }
684 return nil, EAFNOSUPPORT
685 }
686
687 func Accept(fd int) (nfd int, sa Sockaddr, err error) {
688 return Accept4(fd, 0)
689 }
690
691 func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
692 var rsa RawSockaddrAny
693 var len _Socklen = SizeofSockaddrAny
694 nfd, err = accept4(fd, &rsa, &len, flags)
695 if err != nil {
696 return
697 }
698 if len > SizeofSockaddrAny {
699 panic("RawSockaddrAny too small")
700 }
701 sa, err = anyToSockaddr(&rsa)
702 if err != nil {
703 Close(nfd)
704 nfd = 0
705 }
706 return
707 }
708
709 func Getsockname(fd int) (sa Sockaddr, err error) {
710 var rsa RawSockaddrAny
711 var len _Socklen = SizeofSockaddrAny
712 if err = getsockname(fd, &rsa, &len); err != nil {
713 return
714 }
715 return anyToSockaddr(&rsa)
716 }
717
718 func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
719 vallen := _Socklen(4)
720 err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
721 return value, err
722 }
723
724 func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
725 var value IPMreq
726 vallen := _Socklen(SizeofIPMreq)
727 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
728 return &value, err
729 }
730
731 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
732 var value IPMreqn
733 vallen := _Socklen(SizeofIPMreqn)
734 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
735 return &value, err
736 }
737
738 func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
739 var value IPv6Mreq
740 vallen := _Socklen(SizeofIPv6Mreq)
741 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
742 return &value, err
743 }
744
745 func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
746 var value IPv6MTUInfo
747 vallen := _Socklen(SizeofIPv6MTUInfo)
748 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
749 return &value, err
750 }
751
752 func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
753 var value ICMPv6Filter
754 vallen := _Socklen(SizeofICMPv6Filter)
755 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
756 return &value, err
757 }
758
759 func GetsockoptUcred(fd, level, opt int) (*Ucred, error) {
760 var value Ucred
761 vallen := _Socklen(SizeofUcred)
762 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
763 return &value, err
764 }
765
766 func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
767 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
768 }
769
770 func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
771 var msg Msghdr
772 msg.Name = (*byte)(unsafe.Pointer(rsa))
773 msg.Namelen = uint32(SizeofSockaddrAny)
774 var iov Iovec
775 if len(p) > 0 {
776 iov.Base = &p[0]
777 iov.SetLen(len(p))
778 }
779 var dummy byte
780 if len(oob) > 0 {
781 if len(p) == 0 {
782 var sockType int
783 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
784 if err != nil {
785 return
786 }
787
788 if sockType != SOCK_DGRAM {
789 iov.Base = &dummy
790 iov.SetLen(1)
791 }
792 }
793 msg.Control = &oob[0]
794 msg.SetControllen(len(oob))
795 }
796 msg.Iov = &iov
797 msg.Iovlen = 1
798 if n, err = recvmsg(fd, &msg, flags); err != nil {
799 return
800 }
801 oobn = int(msg.Controllen)
802 recvflags = int(msg.Flags)
803 return
804 }
805
806 func sendmsgN(fd int, p, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
807 var msg Msghdr
808 msg.Name = (*byte)(ptr)
809 msg.Namelen = uint32(salen)
810 var iov Iovec
811 if len(p) > 0 {
812 iov.Base = &p[0]
813 iov.SetLen(len(p))
814 }
815 var dummy byte
816 if len(oob) > 0 {
817 if len(p) == 0 {
818 var sockType int
819 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
820 if err != nil {
821 return 0, err
822 }
823
824 if sockType != SOCK_DGRAM {
825 iov.Base = &dummy
826 iov.SetLen(1)
827 }
828 }
829 msg.Control = &oob[0]
830 msg.SetControllen(len(oob))
831 }
832 msg.Iov = &iov
833 msg.Iovlen = 1
834 if n, err = sendmsg(fd, &msg, flags); err != nil {
835 return 0, err
836 }
837 if len(oob) > 0 && len(p) == 0 {
838 n = 0
839 }
840 return n, nil
841 }
842
843
844 func BindToDevice(fd int, device string) (err error) {
845 return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
846 }
847
848
849
850
851 func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) {
852
853
854
855
856
857
858 var buf [sizeofPtr]byte
859
860
861
862
863
864
865 n := 0
866 if addr%sizeofPtr != 0 {
867 err = ptracePtr(req, pid, addr-addr%sizeofPtr, unsafe.Pointer(&buf[0]))
868 if err != nil {
869 return 0, err
870 }
871 n += copy(out, buf[addr%sizeofPtr:])
872 out = out[n:]
873 }
874
875
876 for len(out) > 0 {
877
878
879 err = ptracePtr(req, pid, addr+uintptr(n), unsafe.Pointer(&buf[0]))
880 if err != nil {
881 return n, err
882 }
883 copied := copy(out, buf[0:])
884 n += copied
885 out = out[copied:]
886 }
887
888 return n, nil
889 }
890
891 func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
892 return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
893 }
894
895 func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
896 return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
897 }
898
899 func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) {
900
901
902
903
904 n := 0
905 if addr%sizeofPtr != 0 {
906 var buf [sizeofPtr]byte
907 err = ptracePtr(peekReq, pid, addr-addr%sizeofPtr, unsafe.Pointer(&buf[0]))
908 if err != nil {
909 return 0, err
910 }
911 n += copy(buf[addr%sizeofPtr:], data)
912 word := *((*uintptr)(unsafe.Pointer(&buf[0])))
913 err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
914 if err != nil {
915 return 0, err
916 }
917 data = data[n:]
918 }
919
920
921 for len(data) > sizeofPtr {
922 word := *((*uintptr)(unsafe.Pointer(&data[0])))
923 err = ptrace(pokeReq, pid, addr+uintptr(n), word)
924 if err != nil {
925 return n, err
926 }
927 n += sizeofPtr
928 data = data[sizeofPtr:]
929 }
930
931
932 if len(data) > 0 {
933 var buf [sizeofPtr]byte
934 err = ptracePtr(peekReq, pid, addr+uintptr(n), unsafe.Pointer(&buf[0]))
935 if err != nil {
936 return n, err
937 }
938 copy(buf[0:], data)
939 word := *((*uintptr)(unsafe.Pointer(&buf[0])))
940 err = ptrace(pokeReq, pid, addr+uintptr(n), word)
941 if err != nil {
942 return n, err
943 }
944 n += len(data)
945 }
946
947 return n, nil
948 }
949
950 func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
951 return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
952 }
953
954 func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
955 return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
956 }
957
958 const (
959 _NT_PRSTATUS = 1
960 )
961
962 func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
963 var iov Iovec
964 iov.Base = (*byte)(unsafe.Pointer(regsout))
965 iov.SetLen(int(unsafe.Sizeof(*regsout)))
966 return ptracePtr(PTRACE_GETREGSET, pid, uintptr(_NT_PRSTATUS), unsafe.Pointer(&iov))
967 }
968
969 func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) {
970 var iov Iovec
971 iov.Base = (*byte)(unsafe.Pointer(regs))
972 iov.SetLen(int(unsafe.Sizeof(*regs)))
973 return ptracePtr(PTRACE_SETREGSET, pid, uintptr(_NT_PRSTATUS), unsafe.Pointer(&iov))
974 }
975
976 func PtraceSetOptions(pid int, options int) (err error) {
977 return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
978 }
979
980 func PtraceGetEventMsg(pid int) (msg uint, err error) {
981 var data _C_long
982 err = ptracePtr(PTRACE_GETEVENTMSG, pid, 0, unsafe.Pointer(&data))
983 msg = uint(data)
984 return
985 }
986
987 func PtraceCont(pid int, signal int) (err error) {
988 return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
989 }
990
991 func PtraceSyscall(pid int, signal int) (err error) {
992 return ptrace(PTRACE_SYSCALL, pid, 0, uintptr(signal))
993 }
994
995 func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
996
997 func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
998
999 func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
1000
1001
1002
1003 func Reboot(cmd int) (err error) {
1004 return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
1005 }
1006
1007 func ReadDirent(fd int, buf []byte) (n int, err error) {
1008 return Getdents(fd, buf)
1009 }
1010
1011 func direntIno(buf []byte) (uint64, bool) {
1012 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
1013 }
1014
1015 func direntReclen(buf []byte) (uint64, bool) {
1016 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
1017 }
1018
1019 func direntNamlen(buf []byte) (uint64, bool) {
1020 reclen, ok := direntReclen(buf)
1021 if !ok {
1022 return 0, false
1023 }
1024 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
1025 }
1026
1027
1028
1029 func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
1030
1031
1032 if data == "" {
1033 return mount(source, target, fstype, flags, nil)
1034 }
1035 datap, err := BytePtrFromString(data)
1036 if err != nil {
1037 return err
1038 }
1039 return mount(source, target, fstype, flags, datap)
1040 }
1041
1042
1043
1044
1045
1046
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 func Getpgrp() (pid int) {
1070 pid, _ = Getpgid(0)
1071 return
1072 }
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104 func runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123 func AllThreadsSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
1124 if cgo_libc_setegid != nil {
1125 return minus1, minus1, ENOTSUP
1126 }
1127 r1, r2, errno := runtime_doAllThreadsSyscall(trap, a1, a2, a3, 0, 0, 0)
1128 return r1, r2, Errno(errno)
1129 }
1130
1131
1132
1133
1134
1135 func AllThreadsSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
1136 if cgo_libc_setegid != nil {
1137 return minus1, minus1, ENOTSUP
1138 }
1139 r1, r2, errno := runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6)
1140 return r1, r2, Errno(errno)
1141 }
1142
1143
1144
1145
1146 func cgocaller(unsafe.Pointer, ...uintptr) uintptr
1147
1148 var cgo_libc_setegid unsafe.Pointer
1149
1150 const minus1 = ^uintptr(0)
1151
1152 func Setegid(egid int) (err error) {
1153 if cgo_libc_setegid == nil {
1154 if _, _, e1 := AllThreadsSyscall(SYS_SETRESGID, minus1, uintptr(egid), minus1); e1 != 0 {
1155 err = errnoErr(e1)
1156 }
1157 } else if ret := cgocaller(cgo_libc_setegid, uintptr(egid)); ret != 0 {
1158 err = errnoErr(Errno(ret))
1159 }
1160 return
1161 }
1162
1163 var cgo_libc_seteuid unsafe.Pointer
1164
1165 func Seteuid(euid int) (err error) {
1166 if cgo_libc_seteuid == nil {
1167 if _, _, e1 := AllThreadsSyscall(SYS_SETRESUID, minus1, uintptr(euid), minus1); e1 != 0 {
1168 err = errnoErr(e1)
1169 }
1170 } else if ret := cgocaller(cgo_libc_seteuid, uintptr(euid)); ret != 0 {
1171 err = errnoErr(Errno(ret))
1172 }
1173 return
1174 }
1175
1176 var cgo_libc_setgid unsafe.Pointer
1177
1178 func Setgid(gid int) (err error) {
1179 if cgo_libc_setgid == nil {
1180 if _, _, e1 := AllThreadsSyscall(sys_SETGID, uintptr(gid), 0, 0); e1 != 0 {
1181 err = errnoErr(e1)
1182 }
1183 } else if ret := cgocaller(cgo_libc_setgid, uintptr(gid)); ret != 0 {
1184 err = errnoErr(Errno(ret))
1185 }
1186 return
1187 }
1188
1189 var cgo_libc_setregid unsafe.Pointer
1190
1191 func Setregid(rgid, egid int) (err error) {
1192 if cgo_libc_setregid == nil {
1193 if _, _, e1 := AllThreadsSyscall(sys_SETREGID, uintptr(rgid), uintptr(egid), 0); e1 != 0 {
1194 err = errnoErr(e1)
1195 }
1196 } else if ret := cgocaller(cgo_libc_setregid, uintptr(rgid), uintptr(egid)); ret != 0 {
1197 err = errnoErr(Errno(ret))
1198 }
1199 return
1200 }
1201
1202 var cgo_libc_setresgid unsafe.Pointer
1203
1204 func Setresgid(rgid, egid, sgid int) (err error) {
1205 if cgo_libc_setresgid == nil {
1206 if _, _, e1 := AllThreadsSyscall(sys_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid)); e1 != 0 {
1207 err = errnoErr(e1)
1208 }
1209 } else if ret := cgocaller(cgo_libc_setresgid, uintptr(rgid), uintptr(egid), uintptr(sgid)); ret != 0 {
1210 err = errnoErr(Errno(ret))
1211 }
1212 return
1213 }
1214
1215 var cgo_libc_setresuid unsafe.Pointer
1216
1217 func Setresuid(ruid, euid, suid int) (err error) {
1218 if cgo_libc_setresuid == nil {
1219 if _, _, e1 := AllThreadsSyscall(sys_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid)); e1 != 0 {
1220 err = errnoErr(e1)
1221 }
1222 } else if ret := cgocaller(cgo_libc_setresuid, uintptr(ruid), uintptr(euid), uintptr(suid)); ret != 0 {
1223 err = errnoErr(Errno(ret))
1224 }
1225 return
1226 }
1227
1228 var cgo_libc_setreuid unsafe.Pointer
1229
1230 func Setreuid(ruid, euid int) (err error) {
1231 if cgo_libc_setreuid == nil {
1232 if _, _, e1 := AllThreadsSyscall(sys_SETREUID, uintptr(ruid), uintptr(euid), 0); e1 != 0 {
1233 err = errnoErr(e1)
1234 }
1235 } else if ret := cgocaller(cgo_libc_setreuid, uintptr(ruid), uintptr(euid)); ret != 0 {
1236 err = errnoErr(Errno(ret))
1237 }
1238 return
1239 }
1240
1241 var cgo_libc_setuid unsafe.Pointer
1242
1243 func Setuid(uid int) (err error) {
1244 if cgo_libc_setuid == nil {
1245 if _, _, e1 := AllThreadsSyscall(sys_SETUID, uintptr(uid), 0, 0); e1 != 0 {
1246 err = errnoErr(e1)
1247 }
1248 } else if ret := cgocaller(cgo_libc_setuid, uintptr(uid)); ret != 0 {
1249 err = errnoErr(Errno(ret))
1250 }
1251 return
1252 }
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 var mapper = &mmapper{
1273 active: make(map[*byte][]byte),
1274 mmap: mmap,
1275 munmap: munmap,
1276 }
1277
1278 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
1279 return mapper.Mmap(fd, offset, length, prot, flags)
1280 }
1281
1282 func Munmap(b []byte) (err error) {
1283 return mapper.Munmap(b)
1284 }
1285
1286
1287
1288
1289
1290
1291
1292
1293 func Getrlimit(resource int, rlim *Rlimit) (err error) {
1294
1295 return prlimit1(0, resource, nil, rlim)
1296 }
1297
1298
1299
1300 func setrlimit(resource int, rlim *Rlimit) (err error) {
1301 return prlimit1(0, resource, rlim, nil)
1302 }
1303
1304
1305
1306
1307
1308
1309
1310
1311 func prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) {
1312 err = prlimit1(pid, resource, newlimit, old)
1313 if err == nil && newlimit != nil && resource == RLIMIT_NOFILE && (pid == 0 || pid == Getpid()) {
1314 origRlimitNofile.Store(nil)
1315 }
1316 return err
1317 }
1318
View as plain text