error_inject_syacall.bpf.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* SPDX-License-Identifier: MIT
  2. *
  3. * Copyright (c) 2022, eunomia-bpf org
  4. * All rights reserved.
  5. */
  6. #define BPF_NO_GLOBAL_DATA
  7. #include <vmlinux.h>
  8. #include <bpf/bpf_helpers.h>
  9. #include <bpf/bpf_tracing.h>
  10. #include "error_inject_syscall.h"
  11. #define MAX_PATH_LEN 256
  12. struct {
  13. __uint(type, BPF_MAP_TYPE_RINGBUF);
  14. __uint(max_entries, 256 * 1024);
  15. } rb SEC(".maps");
  16. struct {
  17. __uint(type, BPF_MAP_TYPE_HASH);
  18. __uint(key_size, sizeof(int));
  19. __uint(value_size, sizeof(char[MAX_PATH_LEN]));
  20. __uint(max_entries, 1024);
  21. } pathname_map SEC(".maps");
  22. SEC("tracepoint/syscalls/sys_enter_openat")
  23. int trace_sys_enter_openat(struct trace_event_raw_sys_enter *ctx) {
  24. char pathname[MAX_PATH_LEN];
  25. u64 addr = ctx->args[1]; // pathname 地址
  26. u32 pid = bpf_get_current_pid_tgid(); // 使用 PID 作为 map 键
  27. int path_len;
  28. // 读取路径字符串
  29. path_len = bpf_probe_read_user_str(pathname, sizeof(pathname) - 1, (void *) addr);
  30. if (path_len < 0) {
  31. bpf_printk("Failed to read pathname string\n");
  32. return 0; // 读取失败,退出
  33. }
  34. // 确保路径字符串以 NULL 结尾
  35. pathname[sizeof(pathname) - 1] = '\0';
  36. // 过滤掉以 "/usr" 开头的路径
  37. if (path_len >= 4 && pathname[0] == '/' && pathname[1] == 'u' && pathname[2] == 's' && pathname[3] == 'r') {
  38. // bpf_printk("Filtered Pathname: %s\n", pathname); // 调试信息
  39. return 0; // 路径以 "/usr" 开头,过滤掉
  40. }
  41. // 将 pathname 存储到 map 中
  42. bpf_map_update_elem(&pathname_map, &pid, pathname, BPF_ANY);
  43. return 0;
  44. }
  45. SEC("tracepoint/syscalls/sys_enter_read")
  46. int trace_sys_enter_read(struct trace_event_raw_sys_enter *ctx) {
  47. bpf_printk("3456\n");
  48. struct event *e;
  49. u32 pid = bpf_get_current_pid_tgid();
  50. char *pathname;
  51. // 从 map 中获取 pathname
  52. pathname = bpf_map_lookup_elem(&pathname_map, &pid);
  53. if (!pathname) {
  54. bpf_printk("Failed to get pathname from map\n");
  55. return 0;
  56. }
  57. // 过滤掉以 "/usr" 开头的路径
  58. if (pathname[0] == '/' && pathname[1] == 'u' && pathname[2] == 's' && pathname[3] == 'r') {
  59. // bpf_printk("Filtered Pathname: %s\n", pathname); // 调试信息
  60. return 0; // 路径以 "/usr" 开头,过滤掉
  61. }
  62. // 预留 ring buffer 空间
  63. e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
  64. if (!e) {
  65. bpf_printk("Failed to reserve space in ring buffer\n");
  66. return 0; // 预留空间失败,退出
  67. }
  68. // 设置命令名为 "cat"
  69. __builtin_memcpy(e->command, "cat", 4); // 包括终止的 null 字符
  70. __builtin_memcpy(e->pathname, pathname, sizeof(e->pathname)); // 复制 pathname
  71. bpf_printk("command: %s, pathname: %s\n", e->command, e->pathname);
  72. // 提交事件到 ring buffer
  73. bpf_ringbuf_submit(e, 0);
  74. bpf_override_return(ctx,-1);
  75. return 0;
  76. }
  77. SEC("tracepoint/syscalls/sys_enter_write")
  78. int trace_sys_enter_write(struct trace_event_raw_sys_enter *ctx) {
  79. struct event *e;
  80. char comm[TASK_COMM_LEN];
  81. int fd = ctx->args[0];
  82. char *buf = (char *)ctx->args[1];
  83. size_t count = (size_t)ctx->args[2];
  84. // 获取当前进程的命令名
  85. bpf_get_current_comm(&comm, sizeof(comm));
  86. // 确保 count 不超出缓冲区限制
  87. if (count > MAX_DATA_LEN) {
  88. count = MAX_DATA_LEN;
  89. }
  90. // 获取文件路径
  91. u32 pid = bpf_get_current_pid_tgid();
  92. // char *pathname = bpf_map_lookup_elem(&pathname_map, &pid);
  93. char *pathname = bpf_map_lookup_elem(&pathname_map, &fd);
  94. if (!pathname) {
  95. bpf_printk("No pathname found for PID: %u\n", pid);
  96. return 0;
  97. }
  98. // 过滤掉以 "/usr" 开头的路径
  99. if (pathname[0] == '/' && pathname[1] == 'u' && pathname[2] == 's' && pathname[3] == 'r') {
  100. bpf_printk("Ignoring write syscall to path: %s\n", pathname);
  101. return 0; // 路径以 "/usr" 开头,过滤掉
  102. }
  103. // 预留 ring buffer 空间
  104. e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
  105. if (!e) {
  106. bpf_printk("Failed to reserve space in ring buffer\n");
  107. return 0;
  108. }
  109. // 读取写入的数据
  110. if (bpf_probe_read(e->data, count, buf) < 0) {
  111. bpf_printk("Failed to read data from buffer\n");
  112. bpf_ringbuf_discard(e, 0);
  113. return 0;
  114. }
  115. e->size = count;
  116. __builtin_memcpy(e->command, comm, sizeof(e->command));
  117. __builtin_memcpy(e->pathname, pathname, sizeof(e->pathname));
  118. bpf_printk("Captured Data: %s\n", e->data);
  119. bpf_printk("Command: %s\n", e->command);
  120. bpf_printk("Size: %zu\n", e->size);
  121. bpf_printk("File: %s\n", e->pathname);
  122. bpf_ringbuf_submit(e, 0);
  123. return 0;
  124. }
  125. SEC("tracepoint/syscalls/sys_enter_mkdir")
  126. int trace_mkdir(struct trace_event_raw_sys_enter *ctx) {
  127. struct event *e;
  128. char pathname[256];
  129. u64 addr = ctx->args[0]; // pathname
  130. int mode = ctx->args[1]; // mode
  131. // Reserve sample from BPF ringbuf
  132. e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
  133. if (!e) {
  134. bpf_printk("Failed to reserve space in ring buffer\n");
  135. return 0;
  136. }
  137. // Read pathname string
  138. if (bpf_probe_read_user_str(pathname, sizeof(pathname), (void *)addr) < 0) {
  139. bpf_ringbuf_discard(e, 0);
  140. bpf_printk("Failed to read pathname string\n");
  141. return 0;
  142. }
  143. // Copy pathname and mode to event
  144. __builtin_memcpy(e->pathname, pathname, sizeof(e->pathname));
  145. e->mode = mode;
  146. // 将命令名 "mkdir" 复制到事件的 command 字段
  147. __builtin_memcpy(e->command, "mkdir", 6); // 包括终止 null 字符
  148. // Print pathname and mode
  149. // 打印 pathname 和 mode
  150. bpf_printk("mkdir called with pathname: %s, mode: %o, command: %s\n", e->pathname, e->mode, e->command);
  151. // Submit the event
  152. bpf_ringbuf_submit(e, 0);
  153. bpf_override_return(ctx,-1);
  154. return 0;
  155. }
  156. char LICENSE[] SEC("license") = "GPL";