diff options
Diffstat (limited to '')
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 549 | ||||
-rw-r--r-- | imgs/all.drawio | 67 | ||||
-rw-r--r-- | imgs/listener.drawio | 106 | ||||
-rw-r--r-- | listener/audit.go | 16 | ||||
-rw-r--r-- | listener/deal.go | 35 | ||||
-rw-r--r-- | listener/global.go | 20 | ||||
-rw-r--r-- | listener/godo.go | 37 | ||||
-rw-r--r-- | listener/mongo.go | 15 | ||||
-rw-r--r-- | listener/organize.go | 20 | ||||
-rw-r--r-- | notes.md | 318 |
11 files changed, 1127 insertions, 57 deletions
@@ -12,3 +12,4 @@ old/go.* | |||
12 | !logs/*.log | 12 | !logs/*.log |
13 | 13 | ||
14 | __debug_bin* | 14 | __debug_bin* |
15 | *.svg \ No newline at end of file | ||
diff --git a/README.md b/README.md new file mode 100644 index 0000000..bd0dbf8 --- /dev/null +++ b/README.md | |||
@@ -0,0 +1,549 @@ | |||
1 | # 项目背景 | ||
2 | |||
3 | 随着 k8s/云原生等技术日渐普及,docker 容器在生产中的应用愈加广泛。由于 docker 并不是一个完整的操作系统,使用的内核依然是宿主机内核,则在 docker 实际使用过程中,可能会遭受攻击或产生泄露,从而威胁其他 docker 或宿主机。因而我们需要对 docker 内部的进程行为、文件修改等进行监视,在出现问题后便于回溯。 | ||
4 | |||
5 | # 设计思路 | ||
6 | |||
7 | ## 整体设计 | ||
8 | |||
9 | 项目整体采用 MVC 的设计方式,设计思路如下图所示: | ||
10 | |||
11 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="550px" height="450px" viewBox="-0.5 -0.5 789 561" content="<mxfile><diagram id="I_XTTxZs5cPDDl4HmgJE" name="第 1 页">7Vldb5swFP01kbaHTYADSR6btN0eWmlSpK19dIMD1gzOjGnIfv1sbPNlqtJ8NG21p+Dra+N77jmXCxmBRVJ8Y3AT39IQkZHnhMUIXI48z/XdifiRlp2yBL6nDBHDoXaqDUv8F2mjo605DlHWcuSUEo43beOKpila8ZYNMka3bbc1Je27bmCELMNyBYlt/YVDHivr1JvU9u8IR7G5sxvM1EwCjbOOJIthSLcNE7gagQWjlKurpFggIsEzuKh110/MVgdjKOVDFmjcHyHJdWwjLyBi6XxNxQ4CG7hSE8GfXB5qvqAJXomJJUwz8XO7rKdkPHxH2v5yny9ZmcIL4eBON0XpWi8KIvl7g9O8EA6/EUslXdQpxMnVQZSTBq26icdonoZIBuOK6W2MOVpu1JG3gnvCFvOE6GkdK2IcFU/i5VZZEPRFNEGc7YSLWTDWidPMnRhKbmseBMYnbnFAG6HmXlTtXadHXOgM9WdrbGWL4IyjFDGD1wMzUH2KaEg/HwaYhP4aJpjIaO3EKwctT3d6GoTHvo2wG/QhPD0CwiZLLUF0IERpeCGLiBitCMwygcphqKEC8zsxcPT1feP6smgOdmaQirjumoN7ffNyUC8qR2aVigSFVnHr5EZES3OmdW8A4JBFiDd4aGeQIQI5fmzv3pcNvfQHxWWN0Zn3OpkPJp2EqlPpVc2i1tkIPLeRisXaqCRHFc8wvrgWX/RDhzKbOAL5G/ggqhuYMyRqInwop5w2fyDBUSrJJbIilA3mUk9YPH0u9ESCw1Au3Fef+oT67vXD6DndOgemfbAI+55KrybCr57/ch26/3V4Xh0CizIwD7E8DKHRh1Oi91pKnJ1ViXsIsfVA1DscXYpjW4rg0OLYLyF/0umGuk3OcC36rY0qbR5fi57dQ+F0TbMPp8LZK6mw5y1tjYnE4t1192B6zu7eC/YsZ5lQB39LVa4ubCdsOHo6jqfKXCN9fk/2jO3Qahh02DPbsxqOnc5G3bfzI1bDicW5nxht36N4A3+AeMHJxHvOXsRtarRS7MtU6pxEpQbvpkoV586l0rH/TKsxVKVBp/nxwclUCuyeJaFpRC/tT45ZDDfyMoQcZuI1H71NsXZLnBf0iNXrE2s3XfuIFQx4hTdAwvJjyZsEsfqkbxjo2CD2dStT/8UQimH92V8xuP7zBFz9Aw==</diagram></mxfile>"> | ||
12 | <defs /> | ||
13 | <g> | ||
14 | <rect x="40" y="450" width="640" height="110" rx="16.5" ry="16.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
15 | <g transform="translate(-0.5 -0.5)"> | ||
16 | <switch> | ||
17 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
18 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 638px; height: 1px; padding-top: 505px; margin-left: 41px;"> | ||
19 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
20 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
21 | <font style="font-size: 18px;" face="Comic Sans MS"> | ||
22 | Linux kernel | ||
23 | </font> | ||
24 | </div> | ||
25 | </div> | ||
26 | </div> | ||
27 | </foreignObject> | ||
28 | <text x="360" y="509" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
29 | Linux kernel | ||
30 | </text> | ||
31 | </switch> | ||
32 | </g> | ||
33 | <rect x="40" y="190" width="160" height="180" rx="24" ry="24" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
34 | <g transform="translate(-0.5 -0.5)"> | ||
35 | <switch> | ||
36 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
37 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 280px; margin-left: 41px;"> | ||
38 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
39 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
40 | listener | ||
41 | <br /> | ||
42 | (godo) | ||
43 | </div> | ||
44 | </div> | ||
45 | </div> | ||
46 | </foreignObject> | ||
47 | <text x="120" y="285" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
48 | listener... | ||
49 | </text> | ||
50 | </switch> | ||
51 | </g> | ||
52 | <path d="M 40 450 L 40 376.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
53 | <path d="M 40 371.12 L 43.5 378.12 L 40 376.37 L 36.5 378.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
54 | <g transform="translate(-0.5 -0.5)"> | ||
55 | <switch> | ||
56 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
57 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 411px; margin-left: 41px;"> | ||
58 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
59 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
60 | connector | ||
61 | </div> | ||
62 | </div> | ||
63 | </div> | ||
64 | </foreignObject> | ||
65 | <text x="41" y="416" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
66 | connector | ||
67 | </text> | ||
68 | </switch> | ||
69 | </g> | ||
70 | <path d="M 200 450 L 200 376.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
71 | <path d="M 200 371.12 L 203.5 378.12 L 200 376.37 L 196.5 378.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
72 | <g transform="translate(-0.5 -0.5)"> | ||
73 | <switch> | ||
74 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
75 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 411px; margin-left: 201px;"> | ||
76 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
77 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
78 | audit log | ||
79 | </div> | ||
80 | </div> | ||
81 | </div> | ||
82 | </foreignObject> | ||
83 | <text x="201" y="416" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
84 | audit log | ||
85 | </text> | ||
86 | </switch> | ||
87 | </g> | ||
88 | <path d="M 120 190 L 294.7 73.53" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
89 | <path d="M 299.07 70.62 L 295.19 77.42 L 294.7 73.53 L 291.3 71.59 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
90 | <g transform="translate(-0.5 -0.5)"> | ||
91 | <switch> | ||
92 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
93 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 131px; margin-left: 210px;"> | ||
94 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
95 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
96 | infos | ||
97 | </div> | ||
98 | </div> | ||
99 | </div> | ||
100 | </foreignObject> | ||
101 | <text x="210" y="136" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
102 | infos | ||
103 | </text> | ||
104 | </switch> | ||
105 | </g> | ||
106 | <rect x="280" y="190" width="160" height="180" rx="24" ry="24" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
107 | <g transform="translate(-0.5 -0.5)"> | ||
108 | <switch> | ||
109 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
110 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 280px; margin-left: 281px;"> | ||
111 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
112 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
113 | filter | ||
114 | </div> | ||
115 | </div> | ||
116 | </div> | ||
117 | </foreignObject> | ||
118 | <text x="360" y="285" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
119 | filter | ||
120 | </text> | ||
121 | </switch> | ||
122 | </g> | ||
123 | <path d="M 360 183.63 L 360 146.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
124 | <path d="M 360 188.88 L 356.5 181.88 L 360 183.63 L 363.5 181.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
125 | <path d="M 360 141.12 L 363.5 148.12 L 360 146.37 L 356.5 148.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
126 | <rect x="550" y="190" width="130" height="180" rx="19.5" ry="19.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
127 | <g transform="translate(-0.5 -0.5)"> | ||
128 | <switch> | ||
129 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
130 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 280px; margin-left: 551px;"> | ||
131 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
132 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
133 | Viewer | ||
134 | </div> | ||
135 | </div> | ||
136 | </div> | ||
137 | </foreignObject> | ||
138 | <text x="615" y="285" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
139 | Viewer | ||
140 | </text> | ||
141 | </switch> | ||
142 | </g> | ||
143 | <path d="M 420 70 L 609.58 186.66" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
144 | <path d="M 614.05 189.41 L 606.25 188.73 L 609.58 186.66 L 609.92 182.76 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
145 | <path d="M 300 18 C 300 -6 420 -6 420 18 L 420 122 C 420 146 300 146 300 122 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
146 | <path d="M 300 18 C 300 36 420 36 420 18 M 300 27 C 300 45 420 45 420 27 M 300 36 C 300 54 420 54 420 36" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
147 | <g transform="translate(-0.5 -0.5)"> | ||
148 | <switch> | ||
149 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
150 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 92px; margin-left: 301px;"> | ||
151 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
152 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
153 | mongoDB | ||
154 | </div> | ||
155 | </div> | ||
156 | </div> | ||
157 | </foreignObject> | ||
158 | <text x="360" y="97" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
159 | mongoDB | ||
160 | </text> | ||
161 | </switch> | ||
162 | </g> | ||
163 | <path d="M 727 325 C 727 291 727 274 757 274 C 737 274 737 240 757 240 C 777 240 777 274 757 274 C 787 274 787 291 787 325 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
164 | </g> | ||
165 | </svg> | ||
166 | |||
167 | 项目主要分为信息采集、信息过滤、数据库、信息展示四个模块,其工作方式如下: | ||
168 | |||
169 | - 信息采集模块,在各宿主机上安装、并**以 root 权限启动**,负责监听由 Linux 内核发出的 netlink connector 消息、audit 审计消息,将其整理为有关进程的、有关文件的数据,送入数据库中。 | ||
170 | - 在使用时,用信息过滤模块连接数据库,该模块将从数据库中取出所有的消息并过滤无关内容,得到以 docker 守护进程为根的进程树;并在此树的基础上,对数据库中关于文件的记录进行过滤与整理。完成后,将过滤得到的数据送入数据库。 | ||
171 | - 信息展示模块,简要地展示过滤得到的、有关 docker 的数据。 | ||
172 | |||
173 | ## 信息采集 | ||
174 | |||
175 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="900px" height="250px" viewBox="-0.5 -0.5 1161 321" content="<mxfile><diagram id="bYij1YhiqdmEnY_ocicr" name="第 1 页">7VrLcuI4FP0alp3yAz9YBpLMLNLVXcViepbCFkYV22KEeKS/vq8sydiWKQgY4lCzAevKkqV7zj3SlT1wJ9nuL4aWi+80xunAseLdwH0aOI7jDofwJyzv0uJ7jjQkjMTSZO8NU/IbK6OlrGsS41XtRk5pysmyboxonuOI12yIMbqt3zanaf2pS5RgwzCNUGpa/yExX0hr6AR7+9+YJAv9ZNsfyZoM6ZvVTFYLFNNtxeQ+D9wJo5TLq2w3walwnvaLbPdyoLYcGMM5P6WB68kWG5Su1eQGjp9C2/GcQhcwQv6upu3/t6a64tuqAOURbrDDJQA73tcLj6Ko3mZCMxJBxRTlK/j7Pq3e7ifiP6N5QuOZfjyMWY5A1ip3lYNxwHNLcRkjjlacMrgebxeE4+lSPnwL3APbgmcplOyyjw1mHO8O+ssuUQD6Ypphzt7hFt3A0hxU1A1Vcbvnga3BXVQ44GojUtxLyr738MCFQugAWkFv0LIfoCIlK47zIvrEzwKL+a1jAiOZ6IHNmG6yRCvRW7ZKROjTbf5RqJeMRhj6OAr0DEVvCaPrPP6x5inJcYcEGHk1/G27hQB+CwFGXeAfHsP/Y1CeRRcJkiPw/8ESlIt7HYvhaBOX6JK8YATegFfFY2fCg5zBGECOCRWUydfZDLOvSIGhYx2lQLlUdU6BUW8o4AoKvLZIwBtmebHiq/WXskIPrAQXZJhT9gbTxDuhEyVHJgUGhUJAL9kXlgjXq0tEiXuVH4F3HX4Mrd4sEUPBjyeM0mLqMPOKICi5KEBfr0TVEmYAIJMUF/oxp3sZ+fimoA80CNzjMmF7LTLhBF3wwOmNTrySfL2ryMJpUBag4Fjhcf2d3bdT4LKuBtewBa6GR3AeP4rkBUpRCkoJYNWcINz5gjKSihmYYMobVDJlh1AWCvxLNRbX/8K19eB4qvgkPGPpwrsu5DC1X9WCbBZ4urxvV5R0QzkfHBupVQMhmDNdM8XNksccMVg+qttgE0mGU8TJpt5/Gyqq6U9KikjYNdDVDAgbwMpxqVbVpKrRUSnCuqOmsMvJGB0VJCnncxpvzPxNbcCtlCYmhcD7r2gGUeiOGYbYRbOiyqozCaUkyQXNABnYo7ljEVkE8t9HVZGROBYNP865QTUxV08flOnwkQiWUXIB8CeHo3/IrZc5NMVz3uLOGeWcZr1xp1ZE1aR777alsZ8jdsF5YufcUOxGVxG78IhE9VHrzOxX7/PuTecuXeBOjkQzm8yx2Ae/mcc3lWTurkTwgK+vLYJeW6L2OSJ4ngZeRwL1EWdNAsN2iCo787Y8StsuVEo3qCuc0zzJPVUqjXOjZuLQnVTq9yk9IFe/0gl9fFal19AatNLrQt4EQUdLbHisow554xq8eVZHNve1wsoAucEK6/Unse/XXle/y/hKkWh01Dwh6DASzcT+TiPxVjm9Z+b0nxOJ9hlhaH/1fNNp7qLOPVwbukc66jAGzXOKMuFUryjuLBb9W8Vi24vsF+FcMM4v1rh+ZZiHvHrtDNM3N3OftfU4OQl4sGALWtt+uJZzRPuK0k/MCHhIRNMlgmi1CKJ3nU1J2JEghsc66k4QfXMzW7y2vUsxlOFzAzH0277B63mK8GD5QSNhd4L/47QvcWpuddWHFdEC5eBq43D3LgP4UkIcCGAo7j/QlejsP3N2n/8A</diagram></mxfile>"> | ||
176 | <defs /> | ||
177 | <g> | ||
178 | <path d="M 1040 40 C 1040 -13.33 1160 -13.33 1160 40 L 1160 280 C 1160 333.33 1040 333.33 1040 280 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
179 | <path d="M 1040 40 C 1040 80 1160 80 1160 40 M 1040 60 C 1040 100 1160 100 1160 60 M 1040 80 C 1040 120 1160 120 1160 80" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
180 | <g transform="translate(-0.5 -0.5)"> | ||
181 | <switch> | ||
182 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
183 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 210px; margin-left: 1041px;"> | ||
184 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
185 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
186 | <font face="Comic Sans MS" style="font-size: 18px;"> | ||
187 | mongodb | ||
188 | </font> | ||
189 | </div> | ||
190 | </div> | ||
191 | </div> | ||
192 | </foreignObject> | ||
193 | <text x="1100" y="214" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
194 | mongodb | ||
195 | </text> | ||
196 | </switch> | ||
197 | </g> | ||
198 | <rect x="225" y="30" width="160" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
199 | <path d="M 241 30 L 241 120 M 369 30 L 369 120" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
200 | <g transform="translate(-0.5 -0.5)"> | ||
201 | <switch> | ||
202 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
203 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 126px; height: 1px; padding-top: 75px; margin-left: 241px;"> | ||
204 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
205 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
206 | <font face="Comic Sans MS" style="font-size: 18px;"> | ||
207 | 1. listen to the audit, | ||
208 | <br /> | ||
209 | pass msg down | ||
210 | </font> | ||
211 | </div> | ||
212 | </div> | ||
213 | </div> | ||
214 | </foreignObject> | ||
215 | <text x="304" y="79" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
216 | 1. listen to the audi... | ||
217 | </text> | ||
218 | </switch> | ||
219 | </g> | ||
220 | <rect x="450" y="30" width="210" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
221 | <path d="M 471 30 L 471 120 M 639 30 L 639 120" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
222 | <g transform="translate(-0.5 -0.5)"> | ||
223 | <switch> | ||
224 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
225 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 166px; height: 1px; padding-top: 75px; margin-left: 473px;"> | ||
226 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
227 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
228 | <font style="font-size: 18px;" face="Comic Sans MS"> | ||
229 | 2. Organize recvd msg into events by transection number | ||
230 | </font> | ||
231 | </div> | ||
232 | </div> | ||
233 | </div> | ||
234 | </foreignObject> | ||
235 | <text x="556" y="79" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
236 | 2. Organize recvd msg into e... | ||
237 | </text> | ||
238 | </switch> | ||
239 | </g> | ||
240 | <rect x="385" y="210" width="275" height="90" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
241 | <path d="M 413 210 L 413 300 M 632 210 L 632 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
242 | <g transform="translate(-0.5 -0.5)"> | ||
243 | <switch> | ||
244 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
245 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 255px; margin-left: 414px;"> | ||
246 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
247 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
248 | <font style="font-size: 18px;" face="Comic Sans MS"> | ||
249 | 3. Listen to the kernel connector, gets fork/exit events, pass them down | ||
250 | </font> | ||
251 | </div> | ||
252 | </div> | ||
253 | </div> | ||
254 | </foreignObject> | ||
255 | <text x="523" y="259" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
256 | 3. Listen to the kernel connector, g... | ||
257 | </text> | ||
258 | </switch> | ||
259 | </g> | ||
260 | <rect x="760" y="30" width="150" height="270" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
261 | <path d="M 775 30 L 775 300 M 895 30 L 895 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
262 | <g transform="translate(-0.5 -0.5)"> | ||
263 | <switch> | ||
264 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
265 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 117px; height: 1px; padding-top: 165px; margin-left: 776px;"> | ||
266 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
267 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
268 | <font face="Comic Sans MS" style="font-size: 18px;"> | ||
269 | 4. Deal with events recvd, push pid/file info into db | ||
270 | </font> | ||
271 | </div> | ||
272 | </div> | ||
273 | </div> | ||
274 | </foreignObject> | ||
275 | <text x="835" y="169" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
276 | 4. Deal with events... | ||
277 | </text> | ||
278 | </switch> | ||
279 | </g> | ||
280 | <rect x="0" y="30" width="100" height="270" rx="15" ry="15" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all" /> | ||
281 | <g transform="translate(-0.5 -0.5)"> | ||
282 | <switch> | ||
283 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
284 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 165px; margin-left: 1px;"> | ||
285 | <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
286 | <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> | ||
287 | <font style="font-size: 18px;" face="Comic Sans MS"> | ||
288 | Linux kernel | ||
289 | </font> | ||
290 | </div> | ||
291 | </div> | ||
292 | </div> | ||
293 | </foreignObject> | ||
294 | <text x="50" y="169" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle"> | ||
295 | Linux kernel | ||
296 | </text> | ||
297 | </switch> | ||
298 | </g> | ||
299 | <path d="M 100 97.5 L 218.63 97.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
300 | <path d="M 223.88 97.5 L 216.88 101 L 218.63 97.5 L 216.88 94 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
301 | <g transform="translate(-0.5 -0.5)"> | ||
302 | <switch> | ||
303 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
304 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 98px; margin-left: 164px;"> | ||
305 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
306 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
307 | audit log | ||
308 | </div> | ||
309 | </div> | ||
310 | </div> | ||
311 | </foreignObject> | ||
312 | <text x="164" y="104" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
313 | audit log | ||
314 | </text> | ||
315 | </switch> | ||
316 | </g> | ||
317 | <g transform="translate(-0.5 -0.5)"> | ||
318 | <switch> | ||
319 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
320 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 96px; margin-left: 102px;"> | ||
321 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"> | ||
322 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
323 | audit | ||
324 | </div> | ||
325 | </div> | ||
326 | </div> | ||
327 | </foreignObject> | ||
328 | <text x="102" y="96" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px"> | ||
329 | audit | ||
330 | </text> | ||
331 | </switch> | ||
332 | </g> | ||
333 | <path d="M 100 232.5 L 378.63 232.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
334 | <path d="M 383.88 232.5 L 376.88 236 L 378.63 232.5 L 376.88 229 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
335 | <g transform="translate(-0.5 -0.5)"> | ||
336 | <switch> | ||
337 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
338 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 233px; margin-left: 244px;"> | ||
339 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
340 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
341 | process | ||
342 | </div> | ||
343 | </div> | ||
344 | </div> | ||
345 | </foreignObject> | ||
346 | <text x="244" y="239" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
347 | process | ||
348 | </text> | ||
349 | </switch> | ||
350 | </g> | ||
351 | <g transform="translate(-0.5 -0.5)"> | ||
352 | <switch> | ||
353 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
354 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 231px; margin-left: 102px;"> | ||
355 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"> | ||
356 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
357 | netlink | ||
358 | <br /> | ||
359 | connector | ||
360 | </div> | ||
361 | </div> | ||
362 | </div> | ||
363 | </foreignObject> | ||
364 | <text x="102" y="231" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px"> | ||
365 | netlink... | ||
366 | </text> | ||
367 | </switch> | ||
368 | </g> | ||
369 | <path d="M 385 75 L 443.63 75" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
370 | <path d="M 448.88 75 L 441.88 78.5 L 443.63 75 L 441.88 71.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
371 | <path d="M 660 232.5 L 753.63 232.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
372 | <path d="M 758.88 232.5 L 751.88 236 L 753.63 232.5 L 751.88 229 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
373 | <g transform="translate(-0.5 -0.5)"> | ||
374 | <switch> | ||
375 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
376 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 233px; margin-left: 712px;"> | ||
377 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
378 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
379 | Events | ||
380 | </div> | ||
381 | </div> | ||
382 | </div> | ||
383 | </foreignObject> | ||
384 | <text x="712" y="239" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
385 | Events | ||
386 | </text> | ||
387 | </switch> | ||
388 | </g> | ||
389 | <path d="M 660 97.5 L 753.63 97.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
390 | <path d="M 758.88 97.5 L 751.88 101 L 753.63 97.5 L 751.88 94 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
391 | <g transform="translate(-0.5 -0.5)"> | ||
392 | <switch> | ||
393 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
394 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 98px; margin-left: 712px;"> | ||
395 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
396 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
397 | Events | ||
398 | </div> | ||
399 | </div> | ||
400 | </div> | ||
401 | </foreignObject> | ||
402 | <text x="712" y="104" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
403 | Events | ||
404 | </text> | ||
405 | </switch> | ||
406 | </g> | ||
407 | <path d="M 100 300 L 378.63 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
408 | <path d="M 383.88 300 L 376.88 303.5 L 378.63 300 L 376.88 296.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
409 | <g transform="translate(-0.5 -0.5)"> | ||
410 | <switch> | ||
411 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
412 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 301px; margin-left: 244px;"> | ||
413 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
414 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
415 | process info | ||
416 | </div> | ||
417 | </div> | ||
418 | </div> | ||
419 | </foreignObject> | ||
420 | <text x="244" y="306" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
421 | process info | ||
422 | </text> | ||
423 | </switch> | ||
424 | </g> | ||
425 | <g transform="translate(-0.5 -0.5)"> | ||
426 | <switch> | ||
427 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
428 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 299px; margin-left: 102px;"> | ||
429 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"> | ||
430 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
431 | /proc fs | ||
432 | </div> | ||
433 | </div> | ||
434 | </div> | ||
435 | </foreignObject> | ||
436 | <text x="102" y="299" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px"> | ||
437 | /proc fs | ||
438 | </text> | ||
439 | </switch> | ||
440 | </g> | ||
441 | <path d="M 910 97.5 L 1039.99 96.68" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
442 | <path d="M 1045.24 96.65 L 1038.26 100.19 L 1039.99 96.68 L 1038.22 93.19 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
443 | <g transform="translate(-0.5 -0.5)"> | ||
444 | <switch> | ||
445 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
446 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 98px; margin-left: 978px;"> | ||
447 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
448 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
449 | pid info | ||
450 | </div> | ||
451 | </div> | ||
452 | </div> | ||
453 | </foreignObject> | ||
454 | <text x="978" y="103" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
455 | pid info | ||
456 | </text> | ||
457 | </switch> | ||
458 | </g> | ||
459 | <path d="M 910 232.5 L 1041.67 232.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke" /> | ||
460 | <path d="M 1046.92 232.64 L 1039.92 236.13 L 1041.67 232.63 L 1039.93 229.13 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all" /> | ||
461 | <g transform="translate(-0.5 -0.5)"> | ||
462 | <switch> | ||
463 | <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"> | ||
464 | <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 233px; margin-left: 980px;"> | ||
465 | <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"> | ||
466 | <div style="display: inline-block; font-size: 18px; font-family: "Comic Sans MS"; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;"> | ||
467 | file change | ||
468 | <br /> | ||
469 | info | ||
470 | </div> | ||
471 | </div> | ||
472 | </div> | ||
473 | </foreignObject> | ||
474 | <text x="980" y="239" fill="rgb(0, 0, 0)" font-family="Comic Sans MS" font-size="18px" text-anchor="middle"> | ||
475 | file change... | ||
476 | </text> | ||
477 | </switch> | ||
478 | </g> | ||
479 | </g> | ||
480 | <switch> | ||
481 | <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" /> | ||
482 | <a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"> | ||
483 | <text text-anchor="middle" font-size="10px" x="50%" y="100%"> | ||
484 | Text is not SVG - cannot display | ||
485 | </text> | ||
486 | </a> | ||
487 | </switch> | ||
488 | </svg> | ||
489 | |||
490 | 信息采集模块对应本项目下的 listener 目录,主要负责收集 Linux-kernel 发出的 audit 系统审计消息、netlink connector 进程消息。分为四个协程,各自功能如下: | ||
491 | |||
492 | - 1 号协程,**接收来自内核的 audit 审计消息**,传递给 2 号协程 | ||
493 | - 2 号,拿到 1 号发来的消息。对于 audit 审计消息而言,一个事件会被拆分为多条消息发送,但使用相同的时间戳、事务号。因而 2 号将收到的**消息使用正则表达式进行简单解析,并用哈希表按照事务号存储**,直到收到 eoe(本事件到此结束),**将 hash 表中整理得到的 Event 事件发送给 4 号协程**。 | ||
494 | - 3 号,接收来自内核的 connector 消息,获取其中的进程事件(fork/exit)及进程号(ppid/parentTgid/pid/tgid),并通过/proc 文件系统查询 pid 对应的命令行参数 args、当前运行目录 cwd、根文件系统 rootfs、docker id(从 cgroup 查看),**整理为 Event 事件,发送给 4 号协程** | ||
495 | - 4 号,**接收 Event 事件,判断其类型,分别处理**。代码中事件类型主要有进程复制、进程退出、进程执行文件(execve)、文件打开、文件关闭、写文件、切换根系统(pivot_root)等几种。 | ||
496 | |||
497 | ## 信息过滤 | ||
498 | |||
499 | ### 进程过滤与优化 | ||
500 | |||
501 | 首先,由于 listener 模块在插入时采用了多线程,可能出现同一个进程的两条消息被并行处理、数据库中出现两条记录,因而第一步,是**将相同 pid 的多条记录合并为一条**。 | ||
502 | |||
503 | 现在开始考虑清洗数据的问题。Docker 是一个 C/S 架构的服务,因而我们真正关心的 docker 有关进程一定是 docker 守护进程的后代(虽然可能作为孤儿进程被 systemd 收养)。**过滤进程数据,只需要构建以守护进程为根的进程树**。在信息收集过程中,我们对 docker 守护进程(`/usr/bin/dockerd`)进行了特殊记录,标记了该 pid 的`star=true`。在过滤过程中,主要工作即围绕该 pid 展开。 | ||
504 | |||
505 | - 我们记录的条目以 pid 区分,而这里的 pid 实质上指的是 task id、可能是线程,tgid 才是 task group id 应当理解为进程。因而,为了构建进程树,最简单的办法是将各个 pid 按照 tgid 区分,成为一个新的结构;这些结构代表着进程、是进程树的节点,因而称为 tgidNode。在此过程中,我们也可以整理得到每个 tgid 的所有子代 tgid 编号。 | ||
506 | - 整理出来若干 tgidNode,从标记了 star 的 tgidNode 开始,采用广度优先遍历,得到整个进程树上的所有 tgidNode | ||
507 | |||
508 | 接着,进行**数据优化**: | ||
509 | |||
510 | - 同一个 docker id 使用相同的 rootfs。在记录中,同一个 docker id 只有一个进程进行过 pivot_root,因而需要加以处理。 | ||
511 | - 同一个进程(tgid)的不同线程(pid)可能 ppid/parentTgid 不一样。原因为,在进程(pid==tgid)创建的时候,父进程一定还在;但过一会创建线程的时候,原父进程可能已死、该进程已经被 systemd 收容,所以记录的 ppid/parentTgid 不对。为解决该问题,需要检查每个 pid,如果存在该问题则进行修正,防止在按 pid 溯源时出错。 | ||
512 | - 部分 pid 可能并未收到对应的退出消息。为了部分地解决该问题,我们将进程退出时间(也就是 pid==tgid 的 pid 的退出时间)记录为没有 exit timestamp 的 pid 的退出时间。这样的补全是为了接下来在处理文件时使用。 | ||
513 | |||
514 | ### 文件过滤 | ||
515 | |||
516 | 众所周知,Linux 环境下,进程操作文件使用的是系统调用+文件描述符。 | ||
517 | |||
518 | 在记录的时候,由于 Linux 下进程是通过 open 系统调用,传入文件名和权限,得到文件描述符,使用、关闭时都是操作文件描述符而非文件名,所以记录时应当把已经关闭的和尚未关闭的区分开来。写文件时,在已经打开但尚未关闭的文件里按照 pid+fd 查找,记录写入时间;关闭时,将记录从 fd 表删除,加上关闭时间后存储到关闭的文件里。 | ||
519 | |||
520 | 但在整理时,二者都有写入记录,应该等同视之。将两张表的所有记录提取出来进行筛选,只保留 pid 在进程树上的那些文件记录;而后,对于尚未关闭的文件,查询 pid 退出时间,如有记录,则认为该文件在 pid 退出时才关闭。 | ||
521 | |||
522 | 最后,将处理得到的 tgidNode 构成的进程树、筛选之后的文件,全部记录到数据库里。 | ||
523 | |||
524 | ## 信息展示 | ||
525 | |||
526 | 现在已经获取了进程树和文件修改的详细记录,展示即可。本项目目前是在过滤完成之后,直接由过滤模块将进程树、进程详细信息、文件修改记录全部打印到标准输出。 | ||
527 | |||
528 | # 编译与运行 | ||
529 | |||
530 | 本项目的编译运行较为简单。 | ||
531 | |||
532 | 在将本项目克隆下来后: | ||
533 | |||
534 | ```bash | ||
535 | git submodule --init | ||
536 | cd listener | ||
537 | go build -o godo | ||
538 | cd ../filter | ||
539 | go build -o filter | ||
540 | ``` | ||
541 | |||
542 | 编译完成后,将 godo 放置在宿主机上运行,**godo 必须以 root 权限运行**。有若干命令行参数,可以通过`sudo ./godo -h`查看。注意: | ||
543 | |||
544 | - 指定参数使用等号,如`-diag`参数表示将内核原始 audit 消息输出到指定文件,使用时即`sudo ./godo -diag=1.txt` | ||
545 | - 默认的数据库是本机的 mongodb,端口 27017;如要连接别的数据库,需要使用`-mongo`参数指定其链接,格式为`ip:port`。本处并未设置 mongodb 的用户名、密码,而是放开了权限直接登录。使用的数据库名为"test"。 | ||
546 | - backlog 大小默认为 1GB,最好只大不小。以字节为单位。 | ||
547 | - filter 放置在数据库所在的机器上,连接数据库。使用的数据库为 test,写入的数据库为 cooked。 | ||
548 | |||
549 | 而filter程序则直接放置在**数据库所在机器上**,在需要回溯的时候,直接运行filter程序(数据库没有账号密码控制),会输出进程树、每个进程的参数,及最终受改变的文件列表。 \ No newline at end of file | ||
diff --git a/imgs/all.drawio b/imgs/all.drawio new file mode 100644 index 0000000..acfa35d --- /dev/null +++ b/imgs/all.drawio | |||
@@ -0,0 +1,67 @@ | |||
1 | <mxfile host="65bd71144e"> | ||
2 | <diagram id="I_XTTxZs5cPDDl4HmgJE" name="第 1 页"> | ||
3 | <mxGraphModel dx="1038" dy="446" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> | ||
4 | <root> | ||
5 | <mxCell id="0"/> | ||
6 | <mxCell id="1" parent="0"/> | ||
7 | <mxCell id="2" value="<font face="Comic Sans MS" style="font-size: 18px;">Linux kernel</font>" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
8 | <mxGeometry x="140" y="710" width="640" height="110" as="geometry"/> | ||
9 | </mxCell> | ||
10 | <mxCell id="4" value="listener<br>(godo)" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Comic Sans MS;fontSize=18;" vertex="1" parent="1"> | ||
11 | <mxGeometry x="140" y="450" width="160" height="180" as="geometry"/> | ||
12 | </mxCell> | ||
13 | <mxCell id="10" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=0;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="2" target="4"> | ||
14 | <mxGeometry relative="1" as="geometry"> | ||
15 | <mxPoint x="240" y="670" as="sourcePoint"/> | ||
16 | <mxPoint x="340" y="670" as="targetPoint"/> | ||
17 | </mxGeometry> | ||
18 | </mxCell> | ||
19 | <mxCell id="11" value="connector" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="10"> | ||
20 | <mxGeometry relative="1" as="geometry"/> | ||
21 | </mxCell> | ||
22 | <mxCell id="12" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="2" target="4"> | ||
23 | <mxGeometry relative="1" as="geometry"> | ||
24 | <mxPoint x="240" y="670" as="sourcePoint"/> | ||
25 | <mxPoint x="340" y="670" as="targetPoint"/> | ||
26 | </mxGeometry> | ||
27 | </mxCell> | ||
28 | <mxCell id="13" value="audit log" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="12"> | ||
29 | <mxGeometry relative="1" as="geometry"/> | ||
30 | </mxCell> | ||
31 | <mxCell id="19" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="30"> | ||
32 | <mxGeometry relative="1" as="geometry"> | ||
33 | <mxPoint x="570" y="480" as="sourcePoint"/> | ||
34 | <mxPoint x="345" y="340" as="targetPoint"/> | ||
35 | </mxGeometry> | ||
36 | </mxCell> | ||
37 | <mxCell id="20" value="infos" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="19"> | ||
38 | <mxGeometry relative="1" as="geometry"/> | ||
39 | </mxCell> | ||
40 | <mxCell id="22" value="filter" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Comic Sans MS;fontSize=18;" vertex="1" parent="1"> | ||
41 | <mxGeometry x="380" y="450" width="160" height="180" as="geometry"/> | ||
42 | </mxCell> | ||
43 | <mxCell id="26" value="" style="endArrow=classic;startArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="22" target="30"> | ||
44 | <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||
45 | <mxPoint x="560" y="490" as="sourcePoint"/> | ||
46 | <mxPoint x="400" y="410" as="targetPoint"/> | ||
47 | </mxGeometry> | ||
48 | </mxCell> | ||
49 | <mxCell id="27" value="Viewer" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Comic Sans MS;fontSize=18;" vertex="1" parent="1"> | ||
50 | <mxGeometry x="650" y="450" width="130" height="180" as="geometry"/> | ||
51 | </mxCell> | ||
52 | <mxCell id="29" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="30" target="27"> | ||
53 | <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||
54 | <mxPoint x="455" y="340" as="sourcePoint"/> | ||
55 | <mxPoint x="670" y="530" as="targetPoint"/> | ||
56 | </mxGeometry> | ||
57 | </mxCell> | ||
58 | <mxCell id="30" value="mongoDB" style="shape=datastore;whiteSpace=wrap;html=1;fontFamily=Comic Sans MS;fontSize=18;" vertex="1" parent="1"> | ||
59 | <mxGeometry x="400" y="260" width="120" height="140" as="geometry"/> | ||
60 | </mxCell> | ||
61 | <mxCell id="32" value="" style="shape=actor;whiteSpace=wrap;html=1;fontFamily=Comic Sans MS;fontSize=18;" vertex="1" parent="1"> | ||
62 | <mxGeometry x="827" y="500" width="60" height="85" as="geometry"/> | ||
63 | </mxCell> | ||
64 | </root> | ||
65 | </mxGraphModel> | ||
66 | </diagram> | ||
67 | </mxfile> \ No newline at end of file | ||
diff --git a/imgs/listener.drawio b/imgs/listener.drawio new file mode 100644 index 0000000..3c7408e --- /dev/null +++ b/imgs/listener.drawio | |||
@@ -0,0 +1,106 @@ | |||
1 | <mxfile host="65bd71144e"> | ||
2 | <diagram id="bYij1YhiqdmEnY_ocicr" name="第 1 页"> | ||
3 | <mxGraphModel dx="2344" dy="652" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> | ||
4 | <root> | ||
5 | <mxCell id="0"/> | ||
6 | <mxCell id="1" parent="0"/> | ||
7 | <mxCell id="35" value="<font style="font-size: 18px;" face="Comic Sans MS">mongodb</font>" style="shape=datastore;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
8 | <mxGeometry x="1010" y="80" width="120" height="320" as="geometry"/> | ||
9 | </mxCell> | ||
10 | <mxCell id="37" value="<font style="font-size: 18px;" face="Comic Sans MS">1. listen to the audit,<br>pass msg down</font>" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1"> | ||
11 | <mxGeometry x="195" y="110" width="160" height="90" as="geometry"/> | ||
12 | </mxCell> | ||
13 | <mxCell id="38" value="<font face="Comic Sans MS" style="font-size: 18px;">2. Organize recvd msg into events by transection number</font>" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1"> | ||
14 | <mxGeometry x="420" y="110" width="210" height="90" as="geometry"/> | ||
15 | </mxCell> | ||
16 | <mxCell id="39" value="<font face="Comic Sans MS" style="font-size: 18px;">3. Listen to the kernel connector, gets fork/exit events, pass them down</font>" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1"> | ||
17 | <mxGeometry x="355" y="290" width="275" height="90" as="geometry"/> | ||
18 | </mxCell> | ||
19 | <mxCell id="40" value="<font style="font-size: 18px;" face="Comic Sans MS">4. Deal with events recvd, push pid/file info into db</font>" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1"> | ||
20 | <mxGeometry x="730" y="110" width="150" height="270" as="geometry"/> | ||
21 | </mxCell> | ||
22 | <mxCell id="42" value="<font face="Comic Sans MS" style="font-size: 18px;">Linux kernel</font>" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
23 | <mxGeometry x="-30" y="110" width="100" height="270" as="geometry"/> | ||
24 | </mxCell> | ||
25 | <mxCell id="44" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="42" target="37"> | ||
26 | <mxGeometry relative="1" as="geometry"> | ||
27 | <mxPoint x="100" y="180" as="sourcePoint"/> | ||
28 | <mxPoint x="240" y="190" as="targetPoint"/> | ||
29 | </mxGeometry> | ||
30 | </mxCell> | ||
31 | <mxCell id="45" value="audit log" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="44"> | ||
32 | <mxGeometry relative="1" as="geometry"/> | ||
33 | </mxCell> | ||
34 | <mxCell id="46" value="audit" style="edgeLabel;resizable=0;html=1;align=left;verticalAlign=bottom;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="44"> | ||
35 | <mxGeometry x="-1" relative="1" as="geometry"/> | ||
36 | </mxCell> | ||
37 | <mxCell id="47" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="42" target="39"> | ||
38 | <mxGeometry relative="1" as="geometry"> | ||
39 | <mxPoint x="80" y="190" as="sourcePoint"/> | ||
40 | <mxPoint x="240" y="190" as="targetPoint"/> | ||
41 | </mxGeometry> | ||
42 | </mxCell> | ||
43 | <mxCell id="48" value="process" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="47"> | ||
44 | <mxGeometry relative="1" as="geometry"/> | ||
45 | </mxCell> | ||
46 | <mxCell id="49" value="netlink<br>connector" style="edgeLabel;resizable=0;html=1;align=left;verticalAlign=bottom;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="47"> | ||
47 | <mxGeometry x="-1" relative="1" as="geometry"/> | ||
48 | </mxCell> | ||
49 | <mxCell id="50" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="37" target="38"> | ||
50 | <mxGeometry width="50" height="50" relative="1" as="geometry"> | ||
51 | <mxPoint x="370" y="220" as="sourcePoint"/> | ||
52 | <mxPoint x="420" y="170" as="targetPoint"/> | ||
53 | </mxGeometry> | ||
54 | </mxCell> | ||
55 | <mxCell id="52" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="39" target="40"> | ||
56 | <mxGeometry relative="1" as="geometry"> | ||
57 | <mxPoint x="770" y="190" as="sourcePoint"/> | ||
58 | <mxPoint x="870" y="190" as="targetPoint"/> | ||
59 | </mxGeometry> | ||
60 | </mxCell> | ||
61 | <mxCell id="53" value="Events" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="52"> | ||
62 | <mxGeometry relative="1" as="geometry"/> | ||
63 | </mxCell> | ||
64 | <mxCell id="54" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="38" target="40"> | ||
65 | <mxGeometry relative="1" as="geometry"> | ||
66 | <mxPoint x="770" y="190" as="sourcePoint"/> | ||
67 | <mxPoint x="770" y="180" as="targetPoint"/> | ||
68 | </mxGeometry> | ||
69 | </mxCell> | ||
70 | <mxCell id="55" value="Events" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="54"> | ||
71 | <mxGeometry relative="1" as="geometry"/> | ||
72 | </mxCell> | ||
73 | <mxCell id="56" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="42" target="39"> | ||
74 | <mxGeometry relative="1" as="geometry"> | ||
75 | <mxPoint x="270" y="280" as="sourcePoint"/> | ||
76 | <mxPoint x="430" y="280" as="targetPoint"/> | ||
77 | </mxGeometry> | ||
78 | </mxCell> | ||
79 | <mxCell id="57" value="process info" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="56"> | ||
80 | <mxGeometry relative="1" as="geometry"/> | ||
81 | </mxCell> | ||
82 | <mxCell id="58" value="/proc fs" style="edgeLabel;resizable=0;html=1;align=left;verticalAlign=bottom;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="56"> | ||
83 | <mxGeometry x="-1" relative="1" as="geometry"/> | ||
84 | </mxCell> | ||
85 | <mxCell id="63" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.053;entryY=0.302;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="40" target="35"> | ||
86 | <mxGeometry relative="1" as="geometry"> | ||
87 | <mxPoint x="780" y="280" as="sourcePoint"/> | ||
88 | <mxPoint x="880" y="280" as="targetPoint"/> | ||
89 | </mxGeometry> | ||
90 | </mxCell> | ||
91 | <mxCell id="64" value="pid info" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="63"> | ||
92 | <mxGeometry relative="1" as="geometry"/> | ||
93 | </mxCell> | ||
94 | <mxCell id="65" value="" style="endArrow=classic;html=1;fontFamily=Comic Sans MS;fontSize=18;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0.067;entryY=0.727;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="40" target="35"> | ||
95 | <mxGeometry relative="1" as="geometry"> | ||
96 | <mxPoint x="780" y="280" as="sourcePoint"/> | ||
97 | <mxPoint x="880" y="280" as="targetPoint"/> | ||
98 | </mxGeometry> | ||
99 | </mxCell> | ||
100 | <mxCell id="66" value="file change<br>info" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;fontFamily=Comic Sans MS;fontSize=18;" connectable="0" vertex="1" parent="65"> | ||
101 | <mxGeometry relative="1" as="geometry"/> | ||
102 | </mxCell> | ||
103 | </root> | ||
104 | </mxGraphModel> | ||
105 | </diagram> | ||
106 | </mxfile> \ No newline at end of file | ||
diff --git a/listener/audit.go b/listener/audit.go index ed48691..148378c 100644 --- a/listener/audit.go +++ b/listener/audit.go | |||
@@ -13,14 +13,14 @@ func read() error { | |||
13 | // Write netlink response to a file for further analysis or for writing | 13 | // Write netlink response to a file for further analysis or for writing |
14 | // tests cases. | 14 | // tests cases. |
15 | var diagWriter io.Writer | 15 | var diagWriter io.Writer |
16 | if *diag != "" { | 16 | // if *diag != "" { |
17 | f, err := os.OpenFile(*diag, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600) | 17 | // f, err := os.OpenFile(*diag, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o664) |
18 | if err != nil { | 18 | // if err != nil { |
19 | return err | 19 | // return err |
20 | } | 20 | // } |
21 | defer f.Close() | 21 | // defer f.Close() |
22 | diagWriter = f | 22 | // diagWriter = f |
23 | } | 23 | // } |
24 | 24 | ||
25 | log.Println("starting netlink client") | 25 | log.Println("starting netlink client") |
26 | 26 | ||
diff --git a/listener/deal.go b/listener/deal.go index 70c2827..af65ff8 100644 --- a/listener/deal.go +++ b/listener/deal.go | |||
@@ -10,17 +10,8 @@ import ( | |||
10 | "go.mongodb.org/mongo-driver/bson" | 10 | "go.mongodb.org/mongo-driver/bson" |
11 | ) | 11 | ) |
12 | 12 | ||
13 | const ( | ||
14 | dbName string = "test" | ||
15 | pidColName string = "pids" | ||
16 | fdColName string = "fds" | ||
17 | fileColName string = "files" | ||
18 | ) | ||
19 | |||
20 | var pidCol, fdCol, fileCol mongoClient | ||
21 | |||
22 | func initPidCol() (err error) { | 13 | func initPidCol() (err error) { |
23 | // TODO: 这里是否需要补全一下进程信息? | 14 | // 这里是否需要补全一下进程信息? |
24 | dirs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", containerdPid)) | 15 | dirs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", containerdPid)) |
25 | if err != nil { | 16 | if err != nil { |
26 | return err | 17 | return err |
@@ -41,6 +32,9 @@ func initPidCol() (err error) { | |||
41 | process.Star = true | 32 | process.Star = true |
42 | } | 33 | } |
43 | err = pidCol.InsertOne(process) | 34 | err = pidCol.InsertOne(process) |
35 | if err != nil { | ||
36 | return err | ||
37 | } | ||
44 | } | 38 | } |
45 | return nil | 39 | return nil |
46 | } | 40 | } |
@@ -49,27 +43,6 @@ func deal() { | |||
49 | defer wg.Done() | 43 | defer wg.Done() |
50 | var cooked Event | 44 | var cooked Event |
51 | var ok bool | 45 | var ok bool |
52 | var err error | ||
53 | |||
54 | if err = pidCol.init(dbName, pidColName); err != nil { | ||
55 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
56 | return | ||
57 | } | ||
58 | if err = initPidCol(); err != nil { | ||
59 | fmt.Fprintf(os.Stderr, "Err while initing pidcol: %v\n", err) | ||
60 | } | ||
61 | |||
62 | if err = fdCol.init(dbName, fdColName); err != nil { | ||
63 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
64 | return | ||
65 | } | ||
66 | if err = fileCol.init(dbName, fileColName); err != nil { | ||
67 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
68 | } | ||
69 | |||
70 | defer pidCol.Disconnect() | ||
71 | defer fdCol.Disconnect() | ||
72 | defer fileCol.Disconnect() | ||
73 | 46 | ||
74 | for { | 47 | for { |
75 | cooked, ok = <-cookedChan | 48 | cooked, ok = <-cookedChan |
diff --git a/listener/global.go b/listener/global.go index b782284..49d6e94 100644 --- a/listener/global.go +++ b/listener/global.go | |||
@@ -44,12 +44,6 @@ type Event struct { | |||
44 | destPath string | 44 | destPath string |
45 | } | 45 | } |
46 | 46 | ||
47 | var wg sync.WaitGroup // 掌管协程 | ||
48 | var rawChan chan interface{} // 从接收到整理的管道 | ||
49 | var cookedChan chan Event // 整理好的信息的管道 | ||
50 | var syscallTable [500]string //记录一下系统调用 | ||
51 | var containerdPid int | ||
52 | |||
53 | // 插入到数据库的结构 | 47 | // 插入到数据库的结构 |
54 | type Exec struct { | 48 | type Exec struct { |
55 | Timestamp time.Time `bson:"timestamp"` | 49 | Timestamp time.Time `bson:"timestamp"` |
@@ -84,3 +78,17 @@ type File struct { | |||
84 | Written []time.Time `bson:"written"` | 78 | Written []time.Time `bson:"written"` |
85 | CloseTimestamp time.Time `bson:"close_timestamp"` | 79 | CloseTimestamp time.Time `bson:"close_timestamp"` |
86 | } | 80 | } |
81 | |||
82 | const ( | ||
83 | dbName string = "test" | ||
84 | pidColName string = "pids" | ||
85 | fdColName string = "fds" | ||
86 | fileColName string = "files" | ||
87 | ) | ||
88 | |||
89 | var wg sync.WaitGroup // 掌管协程 | ||
90 | var rawChan chan interface{} // 从接收到整理的管道 | ||
91 | var cookedChan chan Event // 整理好的信息的管道 | ||
92 | var syscallTable [500]string //记录一下系统调用 | ||
93 | var containerdPid int // 容器守护进程进程号 | ||
94 | var pidCol, fdCol, fileCol mongoClient // 数据库集合 | ||
diff --git a/listener/godo.go b/listener/godo.go index 8d82231..0e1dc73 100644 --- a/listener/godo.go +++ b/listener/godo.go | |||
@@ -18,14 +18,15 @@ import ( | |||
18 | 18 | ||
19 | var ( | 19 | var ( |
20 | fs = flag.NewFlagSet("audit", flag.ExitOnError) | 20 | fs = flag.NewFlagSet("audit", flag.ExitOnError) |
21 | diag = fs.String("diag", "", "dump raw information from kernel to file") | 21 | diag = fs.String("diag", "godo.log", "dump raw information from kernel to file") |
22 | rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)") | 22 | rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)") |
23 | backlog = fs.Uint("backlog", 8192, "backlog limit") | 23 | backlog = fs.Uint("backlog", 1<<30, "backlog limit") |
24 | immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)") | 24 | immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)") |
25 | receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+") | 25 | receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+") |
26 | mongoURI = fs.String("mongo", "localhost:27017", "mongo database uri") | ||
26 | ) | 27 | ) |
27 | 28 | ||
28 | const bufferPages = 100 | 29 | const bufferPages = 1000 |
29 | 30 | ||
30 | func main() { | 31 | func main() { |
31 | // 检查用户身份,并添加auditd规则,监听所有syscall | 32 | // 检查用户身份,并添加auditd规则,监听所有syscall |
@@ -41,7 +42,6 @@ func main() { | |||
41 | } | 42 | } |
42 | 43 | ||
43 | exec.Command("auditctl", "-D").Run() | 44 | exec.Command("auditctl", "-D").Run() |
44 | exec.Command("auditctl", "-b", "1000000000").Run() | ||
45 | exec.Command("auditctl", "--reset-lost").Run() | 45 | exec.Command("auditctl", "--reset-lost").Run() |
46 | 46 | ||
47 | var auditCmd *exec.Cmd | 47 | var auditCmd *exec.Cmd |
@@ -78,24 +78,45 @@ func main() { | |||
78 | } | 78 | } |
79 | } | 79 | } |
80 | 80 | ||
81 | func coroutine(client *libaudit.AuditClient) { | 81 | func coroutine(client *libaudit.AuditClient) error { |
82 | // 各协程至此开始 | 82 | // 各协程至此开始 |
83 | bufferSize := bufferPages * syscall.Getpagesize() | 83 | bufferSize := bufferPages * syscall.Getpagesize() |
84 | rawChan = make(chan interface{}, bufferSize) | 84 | rawChan = make(chan interface{}, bufferSize) |
85 | cookedChan = make(chan Event, bufferSize) | 85 | cookedChan = make(chan Event, bufferSize) |
86 | 86 | ||
87 | var err error | ||
88 | if err = pidCol.init(dbName, pidColName); err != nil { | ||
89 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
90 | return err | ||
91 | } | ||
92 | if err = initPidCol(); err != nil { | ||
93 | fmt.Fprintf(os.Stderr, "Err while initing pidcol: %v\n", err) | ||
94 | } | ||
95 | |||
96 | if err = fdCol.init(dbName, fdColName); err != nil { | ||
97 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
98 | return err | ||
99 | } | ||
100 | if err = fileCol.init(dbName, fileColName); err != nil { | ||
101 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
102 | } | ||
103 | |||
104 | defer pidCol.Disconnect() | ||
105 | defer fdCol.Disconnect() | ||
106 | defer fileCol.Disconnect() | ||
107 | |||
108 | wg.Add(1) | ||
109 | go deal() | ||
87 | wg.Add(1) | 110 | wg.Add(1) |
88 | go procWatch() | 111 | go procWatch() |
89 | |||
90 | wg.Add(1) | 112 | wg.Add(1) |
91 | go receive(client) | 113 | go receive(client) |
92 | wg.Add(1) | 114 | wg.Add(1) |
93 | go orgnaze() | 115 | go orgnaze() |
94 | wg.Add(1) | ||
95 | go deal() | ||
96 | 116 | ||
97 | wg.Wait() | 117 | wg.Wait() |
98 | time.Sleep(2 * time.Second) | 118 | time.Sleep(2 * time.Second) |
119 | return nil | ||
99 | } | 120 | } |
100 | 121 | ||
101 | func procWatch() error { | 122 | func procWatch() error { |
diff --git a/listener/mongo.go b/listener/mongo.go index a51350e..36c471c 100644 --- a/listener/mongo.go +++ b/listener/mongo.go | |||
@@ -31,18 +31,27 @@ func (mc *mongoClient) init(dbName, colName string) error { | |||
31 | 31 | ||
32 | func (mc *mongoClient) Connect(dbName, colName string) error { | 32 | func (mc *mongoClient) Connect(dbName, colName string) error { |
33 | var err error | 33 | var err error |
34 | mc.client, err = mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) | 34 | // 设置连接MongoDB的参数 |
35 | clientOptions := options.Client().ApplyURI("mongodb://" + *mongoURI) | ||
35 | 36 | ||
37 | // 创建一个带有超时的上下文 | ||
38 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | ||
39 | defer cancel() // 确保在函数退出时取消上下文 | ||
40 | |||
41 | // 使用带超时的上下文连接到MongoDB | ||
42 | mc.client, err = mongo.Connect(ctx, clientOptions) | ||
36 | if err != nil { | 43 | if err != nil { |
37 | return err | 44 | return err |
38 | } | 45 | } |
39 | 46 | ||
40 | ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) | 47 | // 尝试ping数据库以检查连接是否成功 |
41 | err = mc.client.Connect(ctx) | 48 | err = mc.client.Ping(ctx, nil) |
42 | if err != nil { | 49 | if err != nil { |
43 | return err | 50 | return err |
44 | } | 51 | } |
45 | 52 | ||
53 | fmt.Println("Connected to MongoDB!") | ||
54 | |||
46 | mc.col = mc.client.Database(dbName).Collection(colName) | 55 | mc.col = mc.client.Database(dbName).Collection(colName) |
47 | mc.dbName = dbName | 56 | mc.dbName = dbName |
48 | mc.colName = colName | 57 | mc.colName = colName |
diff --git a/listener/organize.go b/listener/organize.go index 0c05eb4..cf6dad3 100644 --- a/listener/organize.go +++ b/listener/organize.go | |||
@@ -2,6 +2,7 @@ package main | |||
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "io" | ||
5 | "os" | 6 | "os" |
6 | "regexp" | 7 | "regexp" |
7 | "strconv" | 8 | "strconv" |
@@ -41,13 +42,30 @@ func orgnaze() { | |||
41 | var raw interface{} | 42 | var raw interface{} |
42 | var rawEvent libaudit.RawAuditMessage | 43 | var rawEvent libaudit.RawAuditMessage |
43 | 44 | ||
45 | var diagWriter io.Writer | ||
46 | var f *os.File | ||
47 | var err error | ||
48 | var fileName string | ||
49 | if *diag != "" { | ||
50 | fileName = *diag | ||
51 | } else { | ||
52 | fileName = "godo.log" | ||
53 | } | ||
54 | |||
55 | f, err = os.OpenFile(fileName, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o664) | ||
56 | if err != nil { | ||
57 | f = nil | ||
58 | } | ||
59 | defer f.Close() | ||
60 | diagWriter = f | ||
61 | |||
44 | for { | 62 | for { |
45 | raw, ok = <-rawChan | 63 | raw, ok = <-rawChan |
46 | if !ok { | 64 | if !ok { |
47 | break | 65 | break |
48 | } | 66 | } |
49 | rawEvent = raw.(libaudit.RawAuditMessage) | 67 | rawEvent = raw.(libaudit.RawAuditMessage) |
50 | // fmt.Printf("type=%v msg=%s\n", rawEvent.Type, rawEvent.Data) | 68 | fmt.Fprintf(diagWriter, "type=%v msg=%s\n", rawEvent.Type, rawEvent.Data) |
51 | 69 | ||
52 | switch rawEvent.Type { | 70 | switch rawEvent.Type { |
53 | case auparse.AUDIT_SYSCALL: | 71 | case auparse.AUDIT_SYSCALL: |
diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..932e811 --- /dev/null +++ b/notes.md | |||
@@ -0,0 +1,318 @@ | |||
1 | # 背景说明 | ||
2 | |||
3 | 本文档对[godo](https://git.qin-juan-ge-zhu.top/godo)编写过程中新了解到的技术、遇到的问题进行简要说明,以备所需。 | ||
4 | |||
5 | # 系统调用 | ||
6 | |||
7 | As is universually acknowledged, 操作系统、尤其是类 Unix 操作系统,以系统调用的形式对应用程序提供服务。系统调用是名称,有系统调用号与之对应(同一版本的内核在不同架构的 cpu 上,系统调用号可能不一样)。有的时候我们需要了解一些内核行为,但却不知道从何下手。可以通过查看内核源码来学习。 | ||
8 | |||
9 | 系统调用可以在源码中查找到。由于本项目使用的是 centos 7,内核版本 3.10.0-1160、cpu 为 x86-64 架构,兹以该版本内核为例说明。 | ||
10 | |||
11 | 要查看 fork 的系统调用号,查看`arch/x86/syscalls/syscall_64.tbl`。想要查看其具体的实现,则在源码根目录下执行`grep -rInP "SYSCALL_DEFINE\d\(fork"`,其中 SYSCALL_DEFINE+数字是 kernel 中定义的宏,展开即完整的函数声明。通过这种查找办法,我们可以快速地定位内核中对系统调用的处理函数,查看其工作原理。查看其他的内核相关内容也可以采取类似办法,即先用 grep 定位大致范围、看都有什么地方用到,然后找到真正起作用的地方,读相关代码。 | ||
12 | |||
13 | 使用这些系统调用有两种办法: | ||
14 | |||
15 | - 在 C 语言中直接调用同名函数,但大概率经过了 glibc 的封装 | ||
16 | - 手动封装。如下: | ||
17 | |||
18 | ```c | ||
19 | #include <stdio.h> | ||
20 | #include <sys/syscall.h> | ||
21 | #include <sys/types.h> | ||
22 | #include <sys/wait.h> | ||
23 | #include <unistd.h> | ||
24 | |||
25 | int main(){ | ||
26 | pid_t pid = syscall(SYS_fork); | ||
27 | // syscall是一个变参函数,第一个参数是系统调用号,接下来的是系统调用的各个参数 | ||
28 | // syscall定义在 unistd.h | ||
29 | // SYS_fork定义在 sys/syscall.h | ||
30 | if(pid == 0) { | ||
31 | printf("Child!\n"); | ||
32 | } else { | ||
33 | printf("Parent!\n"); | ||
34 | } | ||
35 | return 0; | ||
36 | } | ||
37 | ``` | ||
38 | |||
39 | 这种封装方式与经常被用来当作 os 教材的 Linux-0.11/0.12 有所区别。Linux-0.11 环境上,unistd.h 大致如下: | ||
40 | |||
41 | ```c | ||
42 | #ifndef _UNISTD_H | ||
43 | #define _UNISTD_H | ||
44 | |||
45 | ... | ||
46 | #include <sys/stat.h> | ||
47 | #include <sys/times.h> | ||
48 | #include <sys/utsname.h> | ||
49 | #include <utime.h> | ||
50 | |||
51 | #ifdef __LIBRARY__ | ||
52 | |||
53 | #define __NR_setup 0 /* used only by init, to get system going */ | ||
54 | #define __NR_exit 1 | ||
55 | #define __NR_fork 2 | ||
56 | #define __NR_read 3 | ||
57 | #define __NR_write 4 | ||
58 | #define __NR_open 5 | ||
59 | #define __NR_close 6 | ||
60 | ... | ||
61 | |||
62 | #define _syscall0(type,name) \ | ||
63 | type name(void) \ | ||
64 | { \ | ||
65 | long __res; \ | ||
66 | __asm__ volatile ("int $0x80" \ | ||
67 | : "=a" (__res) \ | ||
68 | : "0" (__NR_##name)); \ | ||
69 | if (__res >= 0) \ | ||
70 | return (type) __res; \ | ||
71 | errno = -__res; \ | ||
72 | return -1; \ | ||
73 | } | ||
74 | |||
75 | #define _syscall1(type,name,atype,a) \ | ||
76 | type name(atype a) \ | ||
77 | { \ | ||
78 | long __res; \ | ||
79 | __asm__ volatile ("int $0x80" \ | ||
80 | : "=a" (__res) \ | ||
81 | : "0" (__NR_##name),"b" ((long)(a))); \ | ||
82 | if (__res >= 0) \ | ||
83 | return (type) __res; \ | ||
84 | errno = -__res; \ | ||
85 | return -1; \ | ||
86 | } | ||
87 | |||
88 | ... | ||
89 | #endif /* __LIBRARY__ */ | ||
90 | ... | ||
91 | |||
92 | #endif | ||
93 | ``` | ||
94 | |||
95 | 可以看到,Linux-0.11 上,封装的一般方法为: | ||
96 | |||
97 | ```c | ||
98 | #define __LIBRARY__ // 一定要在unistd.h之前 | ||
99 | #include <unistd.h> | ||
100 | #include <stdio.h> | ||
101 | |||
102 | syscall0(int, fork); // 宏替换后这就是个名为fork的函数的具体实现了 | ||
103 | int main() { | ||
104 | if(fork() == 0) { | ||
105 | printf("Child!\n"); | ||
106 | } else { | ||
107 | printf("Parent!\n"); | ||
108 | } | ||
109 | return 0; | ||
110 | } | ||
111 | ``` | ||
112 | |||
113 | 但是无论如何,一般情况下不推荐手动封装,这不是 release 版该有的做法。 | ||
114 | |||
115 | 此外,从汇编代码来看,Linux-0.11 所用的 80386 芯片,不提供专门的系统调用指令,因而该系统使用的是`int 0x80`中断指令,通过注册中断处理函数进行对应处理;而现代 x86 提供了专门的 syscall 指令,Linux 系统直接用该指令进行系统调用。 | ||
116 | |||
117 | ## 系统调用中的进程与线程 | ||
118 | |||
119 | 一般地,在 Linux 系统上,我们以 pid 指代进程号,而进程可以有多个线程。很显然,真正被调度执行的单元应该是线程,换言之,**是 thread 而非 process 真正地对应着内核中 tasks 表里的一个 task,而每个 task 才具有独一无二的 id**。 | ||
120 | |||
121 | ### 常见系统调用的分析 | ||
122 | |||
123 | 看看这个: | ||
124 | |||
125 | ```c | ||
126 | extern int pthread_create (pthread_t *__restrict __newthread, | ||
127 | const pthread_attr_t *__restrict __attr, | ||
128 | void *(*__start_routine) (void *), | ||
129 | void *__restrict __arg) __THROWNL __nonnull ((1, 3)); | ||
130 | ``` | ||
131 | |||
132 | `pthread_create`函数的第一个参数,就是一个 pthread_t 类型的指针,处理后将 task 的 id 写到指针指向的区域。 | ||
133 | |||
134 | 让我们来看一段简单的代码: | ||
135 | |||
136 | ```c | ||
137 | // test.c | ||
138 | #include <stdio.h> | ||
139 | #include <pthread.h> | ||
140 | #include <sys/syscall.h> | ||
141 | #include <sys/types.h> | ||
142 | #include <unistd.h> | ||
143 | |||
144 | void *test(void *args) { | ||
145 | printf("Hello, I'm %d\n", getpid()); | ||
146 | } | ||
147 | |||
148 | int main() { | ||
149 | pthread_t pthid; | ||
150 | int pid; | ||
151 | pthread_create(&pthid, NULL, test, NULL); | ||
152 | printf("main: thread %ld\n", pthid); | ||
153 | pthread_join(pthid, NULL); | ||
154 | if ((pid = fork()) == 0) { | ||
155 | printf("Hello, I'm %d\n", getpid()); | ||
156 | return 0; | ||
157 | } | ||
158 | printf("main: child process %d\n",pid); | ||
159 | if ((pid = syscall(SYS_fork)) == 0) { | ||
160 | printf("Hello, I'm %d\n", getpid()); | ||
161 | return 0; | ||
162 | } | ||
163 | printf("main: child process %d\n",pid); | ||
164 | return 0; | ||
165 | } | ||
166 | ``` | ||
167 | |||
168 | 当我们使用`strace ./test`来查看上述代码时,会发现情况如下: | ||
169 | |||
170 | ```c | ||
171 | clone(child_stack=0x7f3dd28bbff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f3dd28bc9d0, tls=0x7f3dd28bc700, child_tidptr=0x7f3dd28bc9d0) = 21756 | ||
172 | write(1, "main: thread 139903502108416\n", 29) = 29 | ||
173 | clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f3dd308e9d0) = 21757 | ||
174 | --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21757, si_uid=1000, si_status=0, si_utime=0, si_stime=0} --- | ||
175 | write(1, "main: child process 21757\n", 26) = 26 | ||
176 | fork() = 21758 | ||
177 | --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21758, si_uid=1000, si_status=0, si_utime=0, si_stime=0} --- | ||
178 | write(1, "main: child process 21758\n", 26) = 26 | ||
179 | exit_group(0) = ? | ||
180 | +++ exited with 0 +++ | ||
181 | ``` | ||
182 | |||
183 | 从这样的输出里,我们可以清晰地看到,无论是`pthread_create`还是`fork`(指库函数),本质上都是封装了`clone`系统调用,即使 Linux 本身提供了专门的 fork 系统调用。也许这是 glibc 和 Linux 都想在添加功能的基础上保证代码兼容性?花开两朵各表一枝了属于是。 | ||
184 | |||
185 | 这一结论也可以从 glibc 的代码中得到验证: | ||
186 | |||
187 | ```c | ||
188 | // 文件 glibc-2.18/nptl/sysdeps/unix/sysv/linux/pt-fork.c | ||
189 | pid_t | ||
190 | __fork (void) | ||
191 | { | ||
192 | return __libc_fork (); | ||
193 | } | ||
194 | strong_alias (__fork, fork) | ||
195 | |||
196 | |||
197 | // 文件 glibc-2.18/nptl/sysdeps/unix/sysv/linux/fork.c | ||
198 | pid_t | ||
199 | __libc_fork (void) | ||
200 | { | ||
201 | ... // 一堆不知所云的代码 | ||
202 | #ifdef ARCH_FORK | ||
203 | pid = ARCH_FORK (); | ||
204 | #else | ||
205 | # error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" | ||
206 | pid = INLINE_SYSCALL (fork, 0); | ||
207 | #endif | ||
208 | ... // 又是一堆不知所云的代码 | ||
209 | } | ||
210 | |||
211 | // 文件 glibc-2.18/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c | ||
212 | #define ARCH_FORK() \ | ||
213 | INLINE_SYSCALL (clone, 4, \ | ||
214 | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ | ||
215 | NULL, &THREAD_SELF->tid) | ||
216 | |||
217 | // 文件 glibc-2.18/sysdeps/unix/sysv/linux/x86_64/syscall.S | ||
218 | |||
219 | /* Please consult the file sysdeps/unix/sysv/linux/x86-64/sysdep.h for | ||
220 | more information about the value -4095 used below. */ | ||
221 | .text | ||
222 | ENTRY (syscall) | ||
223 | movq %rdi, %rax /* Syscall number -> rax. */ | ||
224 | movq %rsi, %rdi /* shift arg1 - arg5. */ | ||
225 | movq %rdx, %rsi | ||
226 | movq %rcx, %rdx | ||
227 | movq %r8, %r10 | ||
228 | movq %r9, %r8 | ||
229 | movq 8(%rsp),%r9 /* arg6 is on the stack. */ | ||
230 | syscall /* Do the system call. */ | ||
231 | cmpq $-4095, %rax /* Check %rax for error. */ | ||
232 | jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ | ||
233 | ret /* Return to caller. */ | ||
234 | |||
235 | PSEUDO_END (syscall) | ||
236 | ``` | ||
237 | |||
238 | 可以看到,fork 库函数实际上是掉入了`__libc_fork`,在经过各种处理之后,如果 glibc 中该平台的相关代码里定义了 ARCH_FORK 宏,则调用之;否则会直接调用`INLINE_SYSCALL`(这是 glibc 各个平台的代码里都有的宏);而如果直接调用`syscall`函数手动封装系统调用,则调用什么就是什么。`syscall`函数调用过程涉及延迟绑定等问题,就不是这里的重点了,而且我也没太搞明白,有机会单开一篇吧。 | ||
239 | |||
240 | ### 进程与线程 | ||
241 | |||
242 | 对于一个进程而言,它有很多线程,每个线程有一个号,但整个进程都有主线程的号,称为 tgid,只有一个 tgid 能真正地代表一个进程,而 pid 事实上是 task 的编号。 | ||
243 | |||
244 | 对于 netlink connector 而言,它听到的 fork 并不是 fork,而是 clone;对于 audit,也只能听到 clone 而听不到 fork。这是因为在内核中,fork 也是通过调用 clone 的处理函数来进行的。clone 创建的是一个 task,至于具体是进程还是线程,取决于用的 flag 参数,参见 manual 手册。 | ||
245 | |||
246 | 因而,无论使用 connector 还是 audit,拿到的都是 pid,只不过 connector 可以直接拿到 tgid、据此确定是进程还是线程,而 audit 只能拿到 pid,需要从 clone 的参数里查看是进程还是线程,且拿不到 tgid。这也就是我在项目中选择使用 connector 听进程消息的原因。 | ||
247 | |||
248 | 干巴巴说了这么多,其实就是想说,pid 也许在不同的语境下有不同含义。 | ||
249 | |||
250 | # docker 使用的技术 | ||
251 | |||
252 | ## cgroup | ||
253 | |||
254 | Linux 下用来控制进程资源的东西。没学明白,留缺。姑且抄点书上的内容来占个位置吧。 | ||
255 | |||
256 | cgroup 是 control group 的简写,是 Linux 内核提供的一个特性,用于限制和隔离一组进程对系统资源的使用,也即做进程的 QoS。控制的资源主要包括 cpu、内存、block IO、网络带宽等。该特性自 2.6.24 开始进入内核主线,目前各大发行版都默认打开了该特性。 | ||
257 | |||
258 | 从实现角度,cgroup 实现了一个通用的进程分组框架,而不同类型资源的具体管理由各个 cgroup 子系统实现。截至内核 4.1,已经实现的子系统及其作用如下: | ||
259 | |||
260 | | 子系统 | 作用 | | ||
261 | | ---------- | ----------------------------------------- | | ||
262 | | devices | 设备权限控制 | | ||
263 | | cpuset | 分配指定的 cpu 和内存节点 | | ||
264 | | cpu | 控制 cpu 占用率 | | ||
265 | | cpuacct | 统计 cpu 使用情况 | | ||
266 | | memory | 限制内存使用上限 | | ||
267 | | freezer | 冻结暂停 cgroup 中的进程 | | ||
268 | | net_cls | 配合 tc(traffic controller)限制网络带宽 | | ||
269 | | net_prio | 设置进程网络流量优先级 | | ||
270 | | huge_tlb | 限制 huge_tlb 的使用 | | ||
271 | | perf_event | 允许 Perf 工具基于 cgroup 分组做性能监测 | | ||
272 | |||
273 | cgroup 原生接口通过 cgroupfs 提供,类似于 procfs 和 sysfs,是一种虚拟文件系统。具体使用与分析参见《Docker 进阶与实战》。 | ||
274 | |||
275 | ## namespace | ||
276 | |||
277 | namespace 是将内核的全局资源做封装,使每个 namespace 拥有独立的资源,进程在各自的 namespace 中对相同资源的使用不会互相干扰。比如主机名 hostname 作为全局资源,执行 sethostname 系统调用会影响到其他进程;内核通过实现 UTS namespace,将不同进程分割在不同的 namespace 中,实现了隔离,一个 namespace 修改主机名不影响别的 namespace。 | ||
278 | |||
279 | 目前内核实现了以下几种 namespace: | ||
280 | |||
281 | | namespace | 作用 | | ||
282 | | --------- | ----------------------------------- | | ||
283 | | IPC | 隔离 System V IPC 和 POSIX 消息队列 | | ||
284 | | Network | 隔离网络资源 | | ||
285 | | Mount | 隔离文件系统挂载点 | | ||
286 | | PID | 隔离进程 ID | | ||
287 | | UTS | 隔离主机名和域名 | | ||
288 | | User | 隔离用户 ID 与组 ID | | ||
289 | |||
290 | 对 namespace 的操作主要通过`clone/setns/unshare`三个系统调用来实现。详细的使用也不写了,没用过的东西就不全抄。记得读书和自己实验,补到这里。 | ||
291 | |||
292 | ### 文件系统 | ||
293 | |||
294 | 众所周知,docker 的文件系统是分层的,有镜像文件等一堆东西。文件系统分为若干层,在开启 docker 的时候会被联合挂载到同一个点下,作为 docker 的根目录。这叫做联合挂载,即将多个目录和文件系统挂载到同一个目录下,其中可能有覆盖等。 | ||
295 | |||
296 | docker 进程运行在宿主机的内核上,但是根文件系统又要用 docker 自己挂载的目录,且后来的进程也需要进入该目录。这里采用的技术是 pivot_root,该系统调用允许进程切换根目录。 | ||
297 | |||
298 | 在根目录挂载完成之后,docker 拉起一个初始 shell(正如 Linux-0.11 启动的时候也会有一个 shell 干活),这是 docker 中第一个进程,它调用 pivot_root 切换根目录。在切换完成之后,当我们执行 docker exec 时,这是一个 docker 的新的进程,但该进程不再 pivot_root,而是打开第一个进程的 namespace,通过 setns 系统调用,将自己的 namespace 设置为与其相同。由于 mnt 的 namespace 的存在,进程的根目录也就与第一个进程一样了。 | ||
299 | |||
300 | # 书籍列表 | ||
301 | |||
302 | **毕业之前读完这些属实是有点难为人了,一个比一个硬,一次性啃完能给我门牙崩了;但是定点投放耗材市场之后,估计也不会有啥精力琢磨这些玩意了**。能读一点是一点吧。 | ||
303 | |||
304 | 感觉自己现在已经染上班味了,绝症,没得治。 | ||
305 | |||
306 | - SRE:Google 运维解密 | ||
307 | - Linker and Loader | ||
308 | - 有空自己解析一下 ELF? | ||
309 | - Docker 进阶与实战 | ||
310 | - containerd 原理剖析与实战 | ||
311 | - Linux 内核源码情景分析 | ||
312 | - [LFS](https://www.linuxfromscratch.org/lfs/) 网站,自己从软件包开始搭建 Linux | ||
313 | - 构建嵌入式 Linux 系统 | ||
314 | |||
315 | 也许我应该把它们列入进阶版: | ||
316 | |||
317 | - gcc 技术大全 | ||
318 | - 黑客调试技术大全 | ||