diff options
-rwxr-xr-x | build.sh | 7 | ||||
-rw-r--r-- | godo.go | 157 |
2 files changed, 113 insertions, 51 deletions
diff --git a/build.sh b/build.sh deleted file mode 100755 index 8bdadb3..0000000 --- a/build.sh +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | docker_api_version=$(docker version) | ||
5 | docker_api_version=$(docker version | grep API | head -n 1 | awk '{print $3}') | ||
6 | echo "Docker API version is $docker_api_version..." | ||
7 | export DOCKER_API_VERSION=$docker_api_version \ No newline at end of file | ||
@@ -34,26 +34,27 @@ type Event struct { | |||
34 | pid, ppid int | 34 | pid, ppid int |
35 | syscall int | 35 | syscall int |
36 | argc int | 36 | argc int |
37 | args []string | 37 | argv []string |
38 | cwd string | 38 | cwd string |
39 | } | 39 | } |
40 | 40 | ||
41 | type process struct { | 41 | type process struct { |
42 | cmdline string | 42 | timestamp time.Time |
43 | argv []string | 43 | pid, ppid int |
44 | cwd string | 44 | argv []string |
45 | rootfs string | 45 | cwd string |
46 | children []int | 46 | rootfs string |
47 | children []int | ||
47 | } | 48 | } |
48 | 49 | ||
49 | var pids map[int]*process //古希腊掌管进程的神 | 50 | var pids sync.Map // 古希腊掌管进程的神,int->*process |
50 | var containers map[string]int // 古希腊掌管容器的神 | 51 | var wg sync.WaitGroup // 掌管协程 |
51 | var wg sync.WaitGroup // 掌管协程 | 52 | var rawChan chan interface{} // 从接收到整理的管道 |
52 | var rawChan chan interface{} // 从接收到整理的管道,这里不是原始数据类型,下文解释 | 53 | var cookedChan chan Event // 整理好的信息的管道 |
53 | var cookedChan chan Event // 整理好的信息的管道 | ||
54 | |||
55 | var syscallTable [500]string //记录一下系统调用 | 54 | var syscallTable [500]string //记录一下系统调用 |
56 | 55 | ||
56 | var containerdPid int | ||
57 | |||
57 | func main() { | 58 | func main() { |
58 | // 检查用户身份,并添加auditd规则,监听所有syscall | 59 | // 检查用户身份,并添加auditd规则,监听所有syscall |
59 | if os.Geteuid() != 0 { | 60 | if os.Geteuid() != 0 { |
@@ -72,26 +73,42 @@ func main() { | |||
72 | auditCmd = exec.Command("auditctl", "-D") // 清空所有规则 | 73 | auditCmd = exec.Command("auditctl", "-D") // 清空所有规则 |
73 | auditCmd.Run() | 74 | auditCmd.Run() |
74 | // 设置监听规则 | 75 | // 设置监听规则 |
75 | for i := 0; i < 5; i++ { | 76 | for i := 0; i < len(syscall); i++ { |
76 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", syscall[i]) | 77 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", syscall[i]) |
77 | auditCmd.Run() | 78 | auditCmd.Run() |
78 | } | 79 | } |
79 | 80 | ||
80 | // 查找pid | 81 | // 查找pid |
81 | containerdPid, err := getPid() | 82 | containerdPid, err = getPid() |
82 | if err != nil { | 83 | if err != nil { |
83 | fmt.Printf("Error finding containerd: %v\n", err) | 84 | fmt.Printf("Error finding containerd: %v\n", err) |
84 | return | 85 | return |
85 | } | 86 | } |
86 | // 数据结构初始化 | 87 | // 数据结构初始化 |
87 | pids = make(map[int]*process) | 88 | // pids = make(map[int]*process) |
88 | containers = make(map[string]int) | 89 | // containers = make(map[string]int) |
89 | 90 | ||
90 | // 创世之神,1号进程 | 91 | // 创世之神,1号进程 |
91 | pids[1] = &process{rootfs: "/", children: make([]int, 0)} | 92 | // pids[1] = &process{rootfs: "/", children: make([]int, 0)} |
92 | pids[1].children = append(pids[1].children, containerdPid) | 93 | // pids[1].children = append(pids[1].children, containerdPid) |
94 | // 1号进程还是不要在进程树上直接出现了,不然它的小儿子们都会出现 | ||
95 | |||
93 | // /usr/bin/containerd,也就是我们最关注的进程 | 96 | // /usr/bin/containerd,也就是我们最关注的进程 |
94 | pids[containerdPid] = &process{cmdline: "/usr/bin/cmdline", rootfs: "/", children: make([]int, 0)} | 97 | // pids[containerdPid] = &process{rootfs: "/", children: make([]int, 0)} |
98 | pids.Store(containerdPid, &process{ | ||
99 | ppid: 1, | ||
100 | pid: containerdPid, | ||
101 | argv: make([]string, 0), | ||
102 | cwd: "/", | ||
103 | rootfs: "/", | ||
104 | children: make([]int, 0), | ||
105 | }) | ||
106 | p, ok := pids.Load(containerdPid) | ||
107 | if !ok { | ||
108 | fmt.Printf("???\n") | ||
109 | return | ||
110 | } | ||
111 | p.(*process).argv = append(p.(*process).argv, "/usr/bin/containerd") | ||
95 | 112 | ||
96 | // 开始运行,解析命令行参数后监听 | 113 | // 开始运行,解析命令行参数后监听 |
97 | if err := fs.Parse(os.Args[1:]); err != nil { | 114 | if err := fs.Parse(os.Args[1:]); err != nil { |
@@ -148,7 +165,7 @@ func getPid() (int, error) { | |||
148 | return pid, nil | 165 | return pid, nil |
149 | } | 166 | } |
150 | } | 167 | } |
151 | err = fmt.Errorf("Error: no containerd process found.\n") | 168 | err = fmt.Errorf("Error: no containerd process found.") |
152 | return 0, err | 169 | return 0, err |
153 | } | 170 | } |
154 | 171 | ||
@@ -362,7 +379,7 @@ func orgnaze() { | |||
362 | ppid: event.ppid, | 379 | ppid: event.ppid, |
363 | pid: event.pid, | 380 | pid: event.pid, |
364 | argc: 0, | 381 | argc: 0, |
365 | args: make([]string, 0), | 382 | argv: make([]string, 0), |
366 | cwd: "", | 383 | cwd: "", |
367 | } | 384 | } |
368 | } | 385 | } |
@@ -377,10 +394,9 @@ func orgnaze() { | |||
377 | if len(match[i][2]) == 0 { | 394 | if len(match[i][2]) == 0 { |
378 | // 代表着匹配到的是十六进制数 | 395 | // 代表着匹配到的是十六进制数 |
379 | str := hexToAscii(string(match[i][3])) | 396 | str := hexToAscii(string(match[i][3])) |
380 | eventTable[eventId].args = append(eventTable[eventId].args, str) | 397 | eventTable[eventId].argv = append(eventTable[eventId].argv, str) |
381 | fmt.Printf("Origin: \"%s\", Res: \"%s\"\n", match[i][3], str) | ||
382 | } else { | 398 | } else { |
383 | eventTable[eventId].args = append(eventTable[eventId].args, string(match[i][2])) | 399 | eventTable[eventId].argv = append(eventTable[eventId].argv, string(match[i][2])) |
384 | } | 400 | } |
385 | } | 401 | } |
386 | eventTable[eventId].argc = argc | 402 | eventTable[eventId].argc = argc |
@@ -408,30 +424,21 @@ func orgnaze() { | |||
408 | } else { | 424 | } else { |
409 | cmdline = string(match[3]) | 425 | cmdline = string(match[3]) |
410 | } | 426 | } |
411 | pEvent.args = strings.Split(cmdline, " ") | 427 | pEvent.argv = strings.Split(cmdline, " ") |
412 | pEvent.argc = len(eventTable[eventId].args) | 428 | pEvent.argc = len(eventTable[eventId].argv) |
413 | } | ||
414 | // 当读到proctitle的时候,而且是个新进程最好检查一下cwd,如果还为空,找proc | ||
415 | if pEvent.cwd == "" && (pEvent.syscall == 57 || pEvent.syscall == 58 || pEvent.syscall == 59) { | ||
416 | cwdFilePath := fmt.Sprintf("/proc/%d/cwd", pEvent.pid) | ||
417 | pEvent.cwd, err[1] = os.Readlink(cwdFilePath) | ||
418 | if err[1] != nil { | ||
419 | pEvent.cwd = "" | ||
420 | break | ||
421 | } | ||
422 | } | 429 | } |
423 | } | 430 | } |
424 | case auparse.AUDIT_EOE: | 431 | case auparse.AUDIT_EOE: |
425 | if eoeRegex.Match(rawEvent.Data) { | 432 | if eoeRegex.Match(rawEvent.Data) { |
426 | match := eoeRegex.FindSubmatch(rawEvent.Data) | 433 | match := eoeRegex.FindSubmatch(rawEvent.Data) |
427 | eventId, err[0] = strconv.Atoi(string(match[1])) | 434 | eventId, err[0] = strconv.Atoi(string(match[1])) |
428 | // TODO: 事件整理完毕,即刻发出,是否合理呢? | 435 | // ATTENTION: 事件整理完毕,即刻发出,是否合理呢? |
429 | cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验 | 436 | cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验 |
430 | cookedChan <- cooked | 437 | cookedChan <- cooked |
431 | delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地 | 438 | delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地 |
432 | } | 439 | } |
433 | default: | 440 | default: |
434 | // TODO: 这里也需要做防护 | 441 | // ATTENTION: 这里也需要做防护 |
435 | } | 442 | } |
436 | } | 443 | } |
437 | } | 444 | } |
@@ -453,14 +460,76 @@ func deal() { | |||
453 | // args []string | 460 | // args []string |
454 | // cwd string | 461 | // cwd string |
455 | // } | 462 | // } |
456 | fmt.Printf("recv: %v syscall=%d, ppid=%d, pid=%d, cwd=\"%s\", argc=%d, ", cooked.timestamp, cooked.syscall, cooked.ppid, cooked.pid, cooked.cwd, cooked.argc) | 463 | // type process struct { |
457 | if len(cooked.args) != cooked.argc { | 464 | // timestamp time.Time |
458 | fmt.Printf("Fuck!\n") | 465 | // pid, ppid int |
459 | continue | 466 | // argv []string |
467 | // cwd string | ||
468 | // rootfs string | ||
469 | // children []int | ||
470 | // } | ||
471 | switch syscallTable[cooked.syscall] { | ||
472 | case "fork", "vfork", "clone": | ||
473 | ppid := cooked.ppid | ||
474 | pid := cooked.pid | ||
475 | parent, ok := pids.Load(ppid) | ||
476 | if !ok { | ||
477 | break | ||
478 | } | ||
479 | parent.(*process).children = append(parent.(*process).children, pid) | ||
480 | pids.Store(pid, &process{ | ||
481 | timestamp: cooked.timestamp, | ||
482 | pid: cooked.pid, | ||
483 | ppid: cooked.ppid, | ||
484 | argv: cooked.argv, | ||
485 | cwd: cooked.cwd, | ||
486 | children: make([]int, 0), | ||
487 | }) | ||
488 | fmt.Printf("%v syscall=%d, ppid=%d, pid=%d, cwd=\"%s\", argc=%d, ", cooked.timestamp, cooked.syscall, cooked.ppid, cooked.pid, cooked.cwd, cooked.argc) | ||
489 | for i := 0; i < cooked.argc; i++ { | ||
490 | fmt.Printf("arg[%d]=\"%s\", ", i, cooked.argv[i]) | ||
491 | } | ||
492 | fmt.Printf("\n") | ||
493 | case "exit", "exit_group": | ||
494 | _, ok := pids.Load(cooked.pid) | ||
495 | if !ok { | ||
496 | break | ||
497 | } | ||
498 | go deletePid(cooked) | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | func deletePid(cooked Event) { | ||
504 | time.Sleep(1 * time.Second) | ||
505 | Process, ok := pids.Load(cooked.pid) | ||
506 | if !ok { | ||
507 | return | ||
508 | } | ||
509 | pProcess := Process.(*process) | ||
510 | |||
511 | // 先从爹那里注销户籍 | ||
512 | parent, ok := pids.Load(pProcess.ppid) | ||
513 | if ok { | ||
514 | pParent := parent.(*process) | ||
515 | for i, child := range pParent.children { | ||
516 | if child == pProcess.pid { | ||
517 | pParent.children = append(pParent.children[:i], pParent.children[i+1:]...) | ||
518 | break | ||
519 | } | ||
460 | } | 520 | } |
461 | for i := 0; i < cooked.argc; i++ { | 521 | } |
462 | fmt.Printf("arg[%d]=\"%s\", ", i, cooked.args[i]) | 522 | |
523 | // 子进程需要收容 | ||
524 | for i := 0; i < len(pProcess.children); i++ { | ||
525 | child, ok := pids.Load(pProcess.children[i]) | ||
526 | if ok { | ||
527 | child.(*process).ppid = 1 | ||
463 | } | 528 | } |
464 | fmt.Printf("\n") | ||
465 | } | 529 | } |
530 | |||
531 | // 可以去死了 | ||
532 | pids.Delete(cooked.pid) | ||
533 | _, ok = pids.Load(cooked.pid) | ||
534 | fmt.Printf("%v Goodbye, %d! ok = %v\n", time.Now(), cooked.pid, ok) | ||
466 | } | 535 | } |