libcall_linux.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. // GNU/Linux library calls.
  5. package syscall
  6. import (
  7. "unsafe"
  8. )
  9. //sys ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
  10. //__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
  11. //sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
  12. //__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long
  13. func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) {
  14. // The peek requests are machine-size oriented, so we wrap it
  15. // to retrieve arbitrary-length data.
  16. // The ptrace syscall differs from glibc's ptrace.
  17. // Peeks returns the word in *data, not as the return value.
  18. var buf [sizeofPtr]byte
  19. // Leading edge. PEEKTEXT/PEEKDATA don't require aligned
  20. // access (PEEKUSER warns that it might), but if we don't
  21. // align our reads, we might straddle an unmapped page
  22. // boundary and not get the bytes leading up to the page
  23. // boundary.
  24. n := 0
  25. if addr%sizeofPtr != 0 {
  26. err = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
  27. if err != nil {
  28. return 0, err
  29. }
  30. n += copy(out, buf[addr%sizeofPtr:])
  31. out = out[n:]
  32. }
  33. // Remainder.
  34. for len(out) > 0 {
  35. // We use an internal buffer to gaurantee alignment.
  36. // It's not documented if this is necessary, but we're paranoid.
  37. err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
  38. if err != nil {
  39. return n, err
  40. }
  41. copied := copy(out, buf[0:])
  42. n += copied
  43. out = out[copied:]
  44. }
  45. return n, nil
  46. }
  47. func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
  48. return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
  49. }
  50. func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
  51. return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
  52. }
  53. func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) {
  54. // As for ptracePeek, we need to align our accesses to deal
  55. // with the possibility of straddling an invalid page.
  56. // Leading edge.
  57. n := 0
  58. if addr%sizeofPtr != 0 {
  59. var buf [sizeofPtr]byte
  60. err = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
  61. if err != nil {
  62. return 0, err
  63. }
  64. n += copy(buf[addr%sizeofPtr:], data)
  65. word := *((*uintptr)(unsafe.Pointer(&buf[0])))
  66. err = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
  67. if err != nil {
  68. return 0, err
  69. }
  70. data = data[n:]
  71. }
  72. // Interior.
  73. for len(data) > int(sizeofPtr) {
  74. word := *((*uintptr)(unsafe.Pointer(&data[0])))
  75. err = ptrace(pokeReq, pid, addr+uintptr(n), word)
  76. if err != nil {
  77. return n, err
  78. }
  79. n += int(sizeofPtr)
  80. data = data[sizeofPtr:]
  81. }
  82. // Trailing edge.
  83. if len(data) > 0 {
  84. var buf [sizeofPtr]byte
  85. err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
  86. if err != nil {
  87. return n, err
  88. }
  89. copy(buf[0:], data)
  90. word := *((*uintptr)(unsafe.Pointer(&buf[0])))
  91. err = ptrace(pokeReq, pid, addr+uintptr(n), word)
  92. if err != nil {
  93. return n, err
  94. }
  95. n += len(data)
  96. }
  97. return n, nil
  98. }
  99. func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
  100. return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
  101. }
  102. func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
  103. return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
  104. }
  105. func PtraceSetOptions(pid int, options int) (err error) {
  106. return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
  107. }
  108. func PtraceGetEventMsg(pid int) (msg uint, err error) {
  109. var data _C_long
  110. err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
  111. msg = uint(data)
  112. return
  113. }
  114. func PtraceCont(pid int, signal int) (err error) {
  115. return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
  116. }
  117. func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
  118. func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
  119. func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
  120. //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error)
  121. //reboot(magic1 _C_uint, magic2 _C_uint, cmd _C_int, arg *byte) _C_int
  122. func Reboot(cmd int) (err error) {
  123. return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
  124. }
  125. //sys Acct(path string) (err error)
  126. //acct(path *byte) _C_int
  127. //sys Adjtimex(buf *Timex) (state int, err error)
  128. //adjtimex(buf *Timex) _C_int
  129. //sys Fstatfs(fd int, buf *Statfs_t) (err error)
  130. //fstatfs64(fd _C_int, buf *Statfs_t) _C_int
  131. func Gettid() (tid int) {
  132. r1, _, _ := Syscall(SYS_GETTID, 0, 0, 0)
  133. return int(r1)
  134. }
  135. //sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
  136. //getxattr(path *byte, attr *byte, buf *byte, count Size_t) Ssize_t
  137. //sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
  138. //inotify_add_watch(fd _C_int, pathname *byte, mask uint32) _C_int
  139. //sysnb InotifyInit() (fd int, err error)
  140. //inotify_init() _C_int
  141. //sysnb InotifyInit1(flags int) (fd int, err error)
  142. //inotify_init1(flags _C_int) _C_int
  143. //sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error)
  144. //inotify_rm_watch(fd _C_int, wd uint32) _C_int
  145. //sys Klogctl(typ int, buf []byte) (n int, err error)
  146. //klogctl(typ _C_int, bufp *byte, len _C_int) _C_int
  147. //sys Listxattr(path string, dest []byte) (sz int, err error)
  148. //listxattr(path *byte, list *byte, size Size_t) Ssize_t
  149. //sys PivotRoot(newroot string, putold string) (err error)
  150. //pivot_root(newroot *byte, putold *byte) _C_int
  151. //sys Removexattr(path string, attr string) (err error)
  152. //removexattr(path *byte, name *byte) _C_int
  153. //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
  154. //renameat(olddirfd _C_int, oldpath *byte, newdirfd _C_int, newpath *byte) _C_int
  155. //sys Setfsgid(gid int) (err error)
  156. //setfsgid(gid Gid_t) _C_int
  157. //sys Setfsuid(uid int) (err error)
  158. //setfsuid(uid Uid_t) _C_int
  159. //sysnb Setresgid(rgid int, egid int, sgid int) (err error)
  160. //setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) _C_int
  161. //sysnb Setresuid(ruid int, eguid int, suid int) (err error)
  162. //setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) _C_int
  163. //sys Setxattr(path string, attr string, data []byte, flags int) (err error)
  164. //setxattr(path *byte, name *byte, value *byte, size Size_t, flags _C_int) _C_int
  165. //sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error)
  166. //splice(rfd _C_int, roff *_loff_t, wfd _C_int, woff *_loff_t, len Size_t, flags _C_uint) Ssize_t
  167. func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
  168. var lroff _loff_t
  169. var plroff *_loff_t
  170. if roff != nil {
  171. lroff = _loff_t(*roff)
  172. plroff = &lroff
  173. }
  174. var lwoff _loff_t
  175. var plwoff *_loff_t
  176. if woff != nil {
  177. lwoff = _loff_t(*woff)
  178. plwoff = &lwoff
  179. }
  180. n, err = splice(rfd, plroff, wfd, plwoff, len, flags)
  181. if roff != nil {
  182. *roff = int64(lroff)
  183. }
  184. if woff != nil {
  185. *woff = int64(lwoff)
  186. }
  187. return
  188. }
  189. //sys Statfs(path string, buf *Statfs_t) (err error)
  190. //statfs64(path *byte, buf *Statfs_t) _C_int
  191. //sysnb Sysinfo(info *Sysinfo_t) (err error)
  192. //sysinfo(info *Sysinfo_t) _C_int
  193. //sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
  194. //tee(rfd _C_int, wfd _C_int, len Size_t, flags _C_uint) Ssize_t
  195. func Tgkill(tgid int, tid int, sig Signal) error {
  196. r1, _, errno := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
  197. if r1 < 0 {
  198. return errno
  199. }
  200. return nil
  201. }
  202. //sys unlinkat(dirfd int, path string, flags int) (err error)
  203. //unlinkat(dirfd _C_int, path *byte, flags _C_int) _C_int
  204. func Unlinkat(dirfd int, path string) (err error) {
  205. return unlinkat(dirfd, path, 0)
  206. }
  207. //sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2
  208. //umount2(target *byte, flags _C_int) _C_int
  209. //sys Unshare(flags int) (err error)
  210. //unshare(flags _C_int) _C_int