/
linux.go
124 lines (107 loc) · 2.14 KB
/
linux.go
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
// +build linux
package mem
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strconv"
"golang.org/x/sys/unix"
)
func FindProcess(re *regexp.Regexp, blacklistedTitles ...string) ([]Process, error) { //blacklistedTitles not implemented yet
dirs, err := ioutil.ReadDir("/proc")
if err != nil {
return nil, err
}
var pids []int
for _, dir := range dirs {
if pid, err := strconv.Atoi(dir.Name()); err == nil {
pids = append(pids, pid)
}
}
var procs []Process
for _, pid := range pids {
path := fmt.Sprintf("/proc/%d/cmdline", pid)
f, err := os.Open(path)
if err != nil {
continue
}
defer f.Close()
content, err := ioutil.ReadAll(f)
if err != nil {
continue
}
slices := bytes.SplitN(content, []byte{'\x00'}, 2)
if !re.Match(slices[0]) {
continue
}
procs = append(procs, process{pid})
}
if len(procs) < 1 {
return nil, ErrNoProcess
}
return procs, nil
}
type process struct {
pid int
}
func (p process) ExecutablePath() (string, error) {
path := fmt.Sprintf("/proc/%d/exe", p.pid)
path, err := filepath.EvalSymlinks(path)
if err != nil {
return "", err
}
return filepath.Abs(path)
}
func (p process) Close() error {
return nil
}
func (p process) Pid() int {
return p.pid
}
func (p process) ReadAt(b []byte, off int64) (n int, err error) {
localIov := [1]unix.Iovec{
{Base: &b[0]},
}
localIov[0].SetLen(len(b))
remoteIov := [1]unix.RemoteIovec{
{Base: uintptr(off), Len: len(b)},
}
n, err = unix.ProcessVMReadv(p.pid, localIov[:], remoteIov[:], 0)
logRead(b, n, off, err)
return n, err
}
func (p process) Maps() ([]Map, error) {
path := fmt.Sprintf("/proc/%d/maps", p.pid)
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
var maps []Map
s := bufio.NewScanner(f)
for s.Scan() {
var reg region
_, err := fmt.Sscanf(s.Text(), "%x-%x",
®.start, ®.end)
if err != nil && err != io.EOF {
return nil, err
}
maps = append(maps, reg)
}
return maps, nil
}
type region struct {
start int64
end int64
}
func (r region) Start() int64 {
return r.start
}
func (r region) Size() int64 {
return r.end - r.start
}