1 #include <signal.h>
2 #include <stdio.h>
3 #include <time.h>
4 #include <sys/resource.h>
5 #include <bpf/libbpf.h>
6 #include <time.h>
7
8 #include "openat.h"
9 #include "openat.skel.h"
10
11 #include <map>
12 #include <algorithm>
13 #include <tuple>
14 #include <string>
15 #include <set>
16 using namespace std;
17
18
19
20 // cpp code, to compile run `CC=g++ make openat`
21
22 static struct ring_buffer *ring_buf = NULL;
23 static struct openat_bpf *skel = NULL;
24 static int exiting = 0;
int_exit(int sig)25 static void int_exit(int sig) {
26 exiting = 1;
27 if (ring_buf) {
28 ring_buffer__free(ring_buf);
29 ring_buf= NULL;
30 }
31 if (skel){
32 openat_bpf__destroy(skel);
33 skel = NULL;
34 }
35 }
36
37 using xtt = tuple<time_t, string, string>;
38 static map<int, xtt> pids;
39 static set<string> whitelist; // = {"gnome-shell","firefox-esr", "openat"};
event_handler(void * _ctx,void * data,size_t size)40 static int event_handler(void *_ctx, void *data, size_t size) {
41 if (size != sizeof(struct open_event)){
42 printf("receive unmatch size %d\n", (int)size);
43 return 0;
44 }
45 struct open_event* event = (struct open_event*)data;
46 if (event->fname[0]==0) return 0;
47 int pid = event->pid;
48 time_t ctime = time(NULL);
49 if (pids.count(pid)==0 || ctime-get<0>(pids[pid]) > 1000) {
50 char b[128];
51 char comm[128];
52 char host[128];
53 sprintf(b, "/proc/%d/comm", pid);
54 FILE* fp;
55 size_t i=0;
56 fp = fopen(b, "r"); if (fp) {
57 comm[0]=0; fgets(comm, sizeof(comm), fp);
58 while(i<sizeof(comm)&&comm[i]!=0&&comm[i]!='\n'&&comm[i]!='\r') i++;
59 comm[i]=0;
60 fclose(fp);
61 }
62 if (i<1) strcpy(comm, "unknown-command");
63 sprintf(b, "/proc/%d/root/etc/hostname", pid);
64 i=0; fp = fopen(b, "r"); if (fp) {
65 host[0]=0; fgets(host, sizeof(host), fp);
66 while(i<sizeof(host)&&host[i]!=0&&host[i]!='\n'&&host[i]!='\r') i++;
67 host[i]=0;
68 fclose(fp);
69 }
70 if (i<1) strcpy(host, "unknown-host");
71 pids[pid] = make_tuple(ctime, string(comm), string(host));
72 }
73 if (whitelist.count(get<1>(pids[pid]))==0) {
74 printf("[%s@%s] open file <%s>\n", get<1>(pids[pid]).c_str(), get<2>(pids[pid]).c_str(), event->fname);
75 }
76 return 0;
77 }
78
main(int argc,char * argv[])79 int main(int argc, char *argv[]) {
80 int err;
81 char *p = argv[0];
82 signal(SIGINT, int_exit);
83 signal(SIGTERM, int_exit);
84 skel = openat_bpf__open();
85 if (!skel) {
86 fprintf(stderr, "Failed to open and load BPF skeleton\n");
87 return 1;
88 }
89 err = openat_bpf__load(skel);
90 if (err) {
91 fprintf(stderr, "Failed to load and verify BPF skeleton\n");
92 goto cleanup;
93 }
94 err = openat_bpf__attach(skel);
95 if (err) {
96 fprintf(stderr, "Failed to attach BPF skeleton\n");
97 goto cleanup;
98 }
99 ring_buf = ring_buffer__new(bpf_map__fd(skel->maps.opens), event_handler, NULL, NULL);
100 if (!ring_buf) {
101 perror("Fail to alloc ring buf");
102 goto cleanup;
103 }
104 // white list self
105 for (int i=0; p[i]; i++) {
106 if (p[i]=='/') { p+=i; p++; i=-1; }
107 } whitelist.insert(p);
108 for (int i=1; i<argc; i++) whitelist.insert(argv[i]);
109 while (!exiting) {
110 if(ring_buffer__poll(ring_buf, -1) < 0) break;
111 }
112
113 cleanup:
114 int_exit(0);
115 return 0;
116 }
117