From cf5618ff2e2a183c5bdf6444787dccdcbf26ce76 Mon Sep 17 00:00:00 2001 From: We-unite <3205135446@qq.com> Date: Mon, 22 Jul 2024 11:41:59 +0800 Subject: Use mongodb, insert process info into it I failed to print the process tree out. While I'm printing the tree, the tree itself gets changed, maybe deleted. What's more, the output show that there are 4 lines with the same ppid and pid, how an absurd result! It may be caused by multi-thread. So, use database instead. Mongodb uses bson(binary json) to store data but not relational database like mysql, which means it's more easy to use.(?) Beside inserting, I've also solved a question that "fork" is called once but returns twice. For instance, pid 1 forked pid 2, in the audit log it's not an event "syscall=clone,ppid=1,pid=2", but actually two events "syscall=clone,exit=0,ppid=0,pid=1" and "syscall=clone,exit= 2,ppid=0,pid=1", which is just what we see in sys_fork in kernel source. To deal with this, when syscall is clone and exit is 0 we just drop it. Left question: To find out the exit code when a process exit/exit_group, and finish the code to record it in the database. --- src/deal.go | 165 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 64 deletions(-) (limited to 'src/deal.go') diff --git a/src/deal.go b/src/deal.go index fd9f788..118d914 100644 --- a/src/deal.go +++ b/src/deal.go @@ -1,97 +1,134 @@ package main import ( + "context" "fmt" "time" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +const ( + dbName string = "test" + colName string = "pids" ) func deal() { defer wg.Done() var cooked Event var ok bool + + var err error + var mongo *mongo.Client + var res []bson.M + + mongo, err = connect() + if err != nil { + fmt.Printf("Err connecting the mongodb: %v\n", err) + } + pidCol := mongo.Database(dbName).Collection(colName) + + err = pidCol.Drop(context.Background()) + if err != nil { + fmt.Printf("Err drop: %v\n", err) + } + + _, err = pidCol.InsertOne(context.Background(), bson.M{ + "ppid": 1, + "pid": containerdPid, + "cwd": "/", + }) + if err != nil { + fmt.Printf("Err containerd: %v", err) + return + } + + fmt.Printf("Containerd: %d\n", containerdPid) + for { cooked, ok = <-cookedChan if !ok { break } - // type Event struct { - // timestamp time.Time - // pid, ppid int - // syscall int - // argc int - // args []string - // cwd string - // } - // type process struct { - // timestamp time.Time - // pid, ppid int - // argv []string - // cwd string - // rootfs string - // children []int - // } + switch syscallTable[cooked.syscall] { case "fork", "vfork", "clone": - ppid := cooked.ppid - pid := cooked.pid - parent, ok := pids.Load(ppid) - if !ok { + // 有无父进程在观察中 + res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.ppid}) + if err != nil || len(res) != 1 { break } - parent.(*process).children = append(parent.(*process).children, pid) - pids.Store(pid, &process{ - timestamp: cooked.timestamp, - pid: cooked.pid, - ppid: cooked.ppid, - argv: cooked.argv, - cwd: cooked.cwd, - children: make([]int, 0), + + // 自身是否已经记录 + res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.pid}) + if err != nil { + fmt.Printf("Err finding: %v\n", err) + break + } else if len(res) != 0 { + fmt.Printf("Err inserting pid %v: already in db: %v\n", cooked.pid, res) + break + } + + doc := []bson.A{} + for _, str := range cooked.argv { + doc = append(doc, bson.A{str}) + } + _, err := pidCol.InsertOne(context.Background(), bson.M{ + "timestamp": cooked.timestamp, + "ppid": cooked.ppid, + "pid": cooked.pid, + "cwd": cooked.cwd, + "args": doc, + "children": []bson.M{}, }) - 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) - for i := 0; i < cooked.argc; i++ { - fmt.Printf("arg[%d]=\"%s\", ", i, cooked.argv[i]) + if err != nil { + fmt.Printf("Err insert: %v\n", err) } - fmt.Printf("\n") - case "exit", "exit_group": - _, ok := pids.Load(cooked.pid) - if !ok { - break + + _, err = pidCol.UpdateOne(context.Background(), bson.M{"pid": cooked.pid}, bson.M{ + "$push": bson.M{ + "children": cooked.pid, + }, + }) + if err != nil { + fmt.Printf("Err insert: %v\n", err) } - go deletePid(cooked) + case "exit", "exit_group": + // TODO: 记得补全退出逻辑 + // 上哪找exit code呢? } } } -func deletePid(cooked Event) { - time.Sleep(1 * time.Second) - Process, ok := pids.Load(cooked.pid) - if !ok { - return +func connect() (*mongo.Client, error) { + client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) + + if err != nil { + return nil, err } - pProcess := Process.(*process) - - // 先从爹那里注销户籍 - parent, ok := pids.Load(pProcess.ppid) - if ok { - pParent := parent.(*process) - for i, child := range pParent.children { - if child == pProcess.pid { - pParent.children = append(pParent.children[:i], pParent.children[i+1:]...) - break - } - } + + ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) + err = client.Connect(ctx) + + if err != nil { + return nil, err } - // 子进程需要收容 - for i := 0; i < len(pProcess.children); i++ { - child, ok := pids.Load(pProcess.children[i]) - if ok { - child.(*process).ppid = 1 - } + return client, nil +} + +func findDocuments(client *mongo.Client, dbName, colName string, filter bson.M) ([]bson.M, error) { + collection := client.Database(dbName).Collection(colName) + + cur, err := collection.Find(context.Background(), filter) + if err != nil { + return nil, err } - // 可以去死了 - pids.Delete(cooked.pid) - _, ok = pids.Load(cooked.pid) - fmt.Printf("%v Goodbye, %d! ok = %v\n", time.Now(), cooked.pid, ok) + var results []bson.M + err = cur.All(context.Background(), &results) + + return results, err } -- cgit v1.2.3-70-g09d2