1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
|
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// GNU/Linux library calls.
package syscall
import "unsafe"
//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int)
//openat(dirfd int, path *byte, flags int, mode Mode_t) int
//sys futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int)
//futimesat(dirfd int, path *byte, times *[2]Timeval) int
func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
if len(tv) != 2 {
return EINVAL
}
return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
func Futimes(fd int, tv []Timeval) (errno int) {
// Believe it or not, this is the best we can do on Linux
// (and is what glibc does).
return Utimes("/proc/self/fd/"+itoa(fd), tv)
}
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
// The peek requests are machine-size oriented, so we wrap it
// to retrieve arbitrary-length data.
// The ptrace syscall differs from glibc's ptrace.
// Peeks returns the word in *data, not as the return value.
var buf [sizeofPtr]byte
// Leading edge. PEEKTEXT/PEEKDATA don't require aligned
// access (PEEKUSER warns that it might), but if we don't
// align our reads, we might straddle an unmapped page
// boundary and not get the bytes leading up to the page
// boundary.
n := 0
if addr%sizeofPtr != 0 {
errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return 0, errno
}
n += copy(out, buf[addr%sizeofPtr:])
out = out[n:]
}
// Remainder.
for len(out) > 0 {
// We use an internal buffer to gaurantee alignment.
// It's not documented if this is necessary, but we're paranoid.
errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return n, errno
}
copied := copy(out, buf[0:])
n += copied
out = out[copied:]
}
return n, 0
}
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
}
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
}
func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
// As for ptracePeek, we need to align our accesses to deal
// with the possibility of straddling an invalid page.
// Leading edge.
n := 0
if addr%sizeofPtr != 0 {
var buf [sizeofPtr]byte
errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return 0, errno
}
n += copy(buf[addr%sizeofPtr:], data)
word := *((*uintptr)(unsafe.Pointer(&buf[0])))
errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
if errno != 0 {
return 0, errno
}
data = data[n:]
}
// Interior.
for len(data) > int(sizeofPtr) {
word := *((*uintptr)(unsafe.Pointer(&data[0])))
errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
if errno != 0 {
return n, errno
}
n += int(sizeofPtr)
data = data[sizeofPtr:]
}
// Trailing edge.
if len(data) > 0 {
var buf [sizeofPtr]byte
errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return n, errno
}
copy(buf[0:], data)
word := *((*uintptr)(unsafe.Pointer(&buf[0])))
errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
if errno != 0 {
return n, errno
}
n += len(data)
}
return n, 0
}
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
}
func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
}
func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
}
func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
}
func PtraceSetOptions(pid int, options int) (errno int) {
return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
}
func PtraceGetEventMsg(pid int) (msg uint, errno int) {
var data _C_long
errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
msg = uint(data)
return
}
func PtraceCont(pid int, signal int) (errno int) {
return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
}
func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
// FIXME: mksysinfo needs to produce LINUX_REBOOT_MAGIC[12].
// //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int)
// //reboot(magic1 uint, magic2 uint, cmd int, arg *byte) int
// func Reboot(cmd int) (errno int) {
// return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
// }
//sys Acct(path string) (errno int)
//acct(path *byte) int
// FIXME: mksysinfo Timex
// //sys Adjtimex(buf *Timex) (state int, errno int)
// //adjtimex(buf *Timex) int
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (errno int)
//faccessat(dirfd int, pathname *byte, mode int, flags int) int
//sys Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
//fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int)
//fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int)
//fchownat(dirfd int, path *byte, owner Uid_t, group Gid_t, flags int) int
//sys Flock(fd int, how int) (errno int)
//flock(fd int, how int) int
// FIXME: mksysinfo statfs
// //sys Fstatfs(fd int, buf *Statfs_t) (errno int)
// //fstatfs(fd int, buf *Statfs_t) int
// FIXME: Only available as a syscall.
// //sysnb Gettid() (tid int)
// //gettid() Pid_t
//sys Ioperm(from int, num int, on int) (errno int)
//ioperm(from _C_long, num _C_long, on int) int
//sys Iopl(level int) (errno int)
//iopl(level int) int
// FIXME: mksysinfo linux_dirent
// Or just abandon this function.
// //sys Getdents(fd int, buf []byte) (n int, errno int)
// //getdents64(fd int, buf *byte, count uint)
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int)
//inotify_add_watch(fd int, pathname *byte, mask uint32) int
//sysnb InotifyInit() (fd int, errno int)
//inotify_init() int
//sysnb InotifyInit1(flags int) (fd int, errno int)
//inotify_init1(flags int) int
//sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int)
//inotify_rm_watch(fd int, wd uint32) int
//sys Klogctl(typ int, buf []byte) (n int, errno int)
//klogctl(typ int, bufp *byte, len int) int
//sys Mkdirat(dirfd int, path string, mode uint32) (errno int)
//mkdirat(dirfd int, path *byte, mode Mode_t) int
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (errno int)
//mknodat(dirfd int, path *byte, mode Mode_t, dev _dev_t) int
//sys PivotRoot(newroot string, putold string) (errno int)
//pivot_root(newroot *byte, putold *byte) int
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int)
//renameat(olddirfd int, oldpath *byte, newdirfd int, newpath *byte) int
//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, errno int)
//sendfile64(outfd int, infd int, offset *Offset_t, count Size_t) Ssize_t
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
var soff Offset_t
var psoff *Offset_t
if offset != nil {
psoff = &soff
}
written, errno = sendfile(outfd, infd, psoff, count)
if offset != nil {
*offset = int64(soff)
}
return
}
//sys Setfsgid(gid int) (errno int)
//setfsgid(gid Gid_t) int
//sys Setfsuid(uid int) (errno int)
//setfsuid(uid Uid_t) int
//sysnb Setresgid(rgid int, egid int, sgid int) (errno int)
//setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) int
//sysnb Setresuid(ruid int, eguid int, suid int) (errno int)
//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) int
//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, errno int)
//splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len Size_t, flags uint) Ssize_t
func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int) {
var lroff _loff_t
var plroff *_loff_t
if (roff != nil) {
plroff = &lroff
}
var lwoff _loff_t
var plwoff *_loff_t
if (woff != nil) {
plwoff = &lwoff
}
n, errno = splice(rfd, plroff, wfd, plwoff, len, flags)
if (roff != nil) {
*roff = int64(lroff)
}
if (woff != nil) {
*woff = int64(lwoff)
}
return
}
// FIXME: mksysinfo statfs
// //sys Statfs(path string, buf *Statfs_t) (errno int)
// //statfs(path *byte, buf *Statfs_t) int
//sys SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
//sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
// FIXME: mksysinfo Sysinfo_t
// //sysnb Sysinfo(info *Sysinfo_t) (errno int)
// //sysinfo(info *Sysinfo_t) int
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, errno int)
//tee(rfd int, wfd int, len Size_t, flags uint) Ssize_t
// FIXME: Only available as a syscall.
// //sysnb Tgkill(tgid int, tid int, sig int) (errno int)
// //tgkill(tgid int, tid int, sig int) int
//sys unlinkat(dirfd int, path string, flags int) (errno int)
//unlinkat(dirfd int, path *byte, flags int) int
func Unlinkat(dirfd int, path string) (errno int) {
return unlinkat(dirfd, path, 0)
}
//sys Unmount(target string, flags int) (errno int) = SYS_UMOUNT2
//umount2(target *byte, flags int) int
//sys Unshare(flags int) (errno int)
//unshare(flags int) int
// FIXME: mksysinfo Ustat_t
// //sys Ustat(dev int, ubuf *Ustat_t) (errno int)
// //ustat(dev _dev_t, ubuf *Ustat_t) int
|