proc_events.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* https://cirosantilli.com/linux-kernel-module-cheat#config-proc-events
  2. *
  3. * Adapted from: https://stackoverflow.com/questions/6075013/detect-launching-of-programs-on-linux-platform/8255487#8255487
  4. */
  5. #if defined(__aarch64__)
  6. int main(void) {}
  7. #else
  8. #define _XOPEN_SOURCE 700
  9. #include <errno.h>
  10. #include <linux/cn_proc.h>
  11. #include <linux/connector.h>
  12. #include <linux/netlink.h>
  13. #include <signal.h>
  14. #include <stdbool.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/socket.h>
  19. #include <unistd.h>
  20. static volatile bool need_exit = false;
  21. static int nl_connect() {
  22. int rc;
  23. int nl_sock;
  24. struct sockaddr_nl sa_nl;
  25. nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
  26. if (nl_sock == -1) {
  27. perror("socket");
  28. return -1;
  29. }
  30. sa_nl.nl_family = AF_NETLINK;
  31. sa_nl.nl_groups = CN_IDX_PROC;
  32. sa_nl.nl_pid = getpid();
  33. rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
  34. if (rc == -1) {
  35. perror("bind");
  36. close(nl_sock);
  37. return -1;
  38. }
  39. return nl_sock;
  40. }
  41. static int set_proc_ev_listen(int nl_sock, bool enable) {
  42. int rc;
  43. struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
  44. struct nlmsghdr nl_hdr;
  45. struct __attribute__ ((__packed__)) {
  46. struct cn_msg cn_msg;
  47. enum proc_cn_mcast_op cn_mcast;
  48. };
  49. } nlcn_msg;
  50. memset(&nlcn_msg, 0, sizeof(nlcn_msg));
  51. nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
  52. nlcn_msg.nl_hdr.nlmsg_pid = getpid();
  53. nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
  54. nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
  55. nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
  56. nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
  57. nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;
  58. rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
  59. if (rc == -1) {
  60. perror("netlink send");
  61. return -1;
  62. }
  63. return 0;
  64. }
  65. static int handle_proc_ev(int nl_sock) {
  66. int rc;
  67. struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
  68. struct nlmsghdr nl_hdr;
  69. struct __attribute__ ((__packed__)) {
  70. struct cn_msg cn_msg;
  71. struct proc_event proc_ev;
  72. };
  73. } nlcn_msg;
  74. while (!need_exit) {
  75. rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
  76. if (rc == 0) {
  77. return 0;
  78. } else if (rc == -1) {
  79. if (errno == EINTR) continue;
  80. perror("netlink recv");
  81. return -1;
  82. }
  83. switch (nlcn_msg.proc_ev.what) {
  84. case PROC_EVENT_NONE:
  85. printf("set mcast listen ok\n");
  86. break;
  87. case PROC_EVENT_FORK:
  88. printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n",
  89. nlcn_msg.proc_ev.event_data.fork.parent_pid,
  90. nlcn_msg.proc_ev.event_data.fork.parent_tgid,
  91. nlcn_msg.proc_ev.event_data.fork.child_pid,
  92. nlcn_msg.proc_ev.event_data.fork.child_tgid);
  93. break;
  94. case PROC_EVENT_EXEC:
  95. printf("exec: tid=%d pid=%d\n",
  96. nlcn_msg.proc_ev.event_data.exec.process_pid,
  97. nlcn_msg.proc_ev.event_data.exec.process_tgid);
  98. break;
  99. case PROC_EVENT_UID:
  100. printf("uid change: tid=%d pid=%d from %d to %d\n",
  101. nlcn_msg.proc_ev.event_data.id.process_pid,
  102. nlcn_msg.proc_ev.event_data.id.process_tgid,
  103. nlcn_msg.proc_ev.event_data.id.r.ruid,
  104. nlcn_msg.proc_ev.event_data.id.e.euid);
  105. break;
  106. case PROC_EVENT_GID:
  107. printf("gid change: tid=%d pid=%d from %d to %d\n",
  108. nlcn_msg.proc_ev.event_data.id.process_pid,
  109. nlcn_msg.proc_ev.event_data.id.process_tgid,
  110. nlcn_msg.proc_ev.event_data.id.r.rgid,
  111. nlcn_msg.proc_ev.event_data.id.e.egid);
  112. break;
  113. case PROC_EVENT_EXIT:
  114. printf("exit: tid=%d pid=%d exit_code=%d\n",
  115. nlcn_msg.proc_ev.event_data.exit.process_pid,
  116. nlcn_msg.proc_ev.event_data.exit.process_tgid,
  117. nlcn_msg.proc_ev.event_data.exit.exit_code);
  118. break;
  119. default:
  120. printf("unhandled proc event\n");
  121. break;
  122. }
  123. }
  124. return 0;
  125. }
  126. static void on_sigint(__attribute__ ((unused)) int unused) {
  127. need_exit = true;
  128. }
  129. int main(void) {
  130. int nl_sock;
  131. int rc = EXIT_SUCCESS;
  132. signal(SIGINT, &on_sigint);
  133. siginterrupt(SIGINT, true);
  134. nl_sock = nl_connect();
  135. if (nl_sock == -1)
  136. exit(EXIT_FAILURE);
  137. rc = set_proc_ev_listen(nl_sock, true);
  138. if (rc == -1) {
  139. rc = EXIT_FAILURE;
  140. goto out;
  141. }
  142. rc = handle_proc_ev(nl_sock);
  143. if (rc == -1) {
  144. rc = EXIT_FAILURE;
  145. goto out;
  146. }
  147. set_proc_ev_listen(nl_sock, false);
  148. out:
  149. close(nl_sock);
  150. exit(rc);
  151. }
  152. #endif