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; 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"}; 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 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