syscall.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * syscall.c
  3. *
  4. * System call "stealing" sample.
  5. *
  6. * Disables page protection at a processor level by changing the 16th bit
  7. * in the cr0 register (could be Intel specific).
  8. *
  9. * Based on example by Peter Jay Salzman and
  10. * https://bbs.archlinux.org/viewtopic.php?id=139406
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/moduleparam.h> /* which will have params */
  16. #include <linux/unistd.h> /* The list of system calls */
  17. #include <linux/version.h>
  18. /* For the current (process) structure, we need this to know who the
  19. * current user is.
  20. */
  21. #include <linux/sched.h>
  22. #include <linux/uaccess.h>
  23. /* The in-kernel calls to the ksys_close() syscall were removed in Linux v5.11+.
  24. */
  25. #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
  26. #include <linux/syscalls.h> /* ksys_close() wrapper for backward compatibility */
  27. #define close_fd ksys_close
  28. #else
  29. #include <linux/fdtable.h> /* For close_fd */
  30. #endif
  31. unsigned long **sys_call_table;
  32. unsigned long original_cr0;
  33. /* UID we want to spy on - will be filled from the command line. */
  34. static int uid;
  35. module_param(uid, int, 0644);
  36. /* A pointer to the original system call. The reason we keep this, rather
  37. * than call the original function (sys_open), is because somebody else
  38. * might have replaced the system call before us. Note that this is not
  39. * 100% safe, because if another module replaced sys_open before us,
  40. * then when we are inserted, we will call the function in that module -
  41. * and it might be removed before we are.
  42. *
  43. * Another reason for this is that we can not get sys_open.
  44. * It is a static variable, so it is not exported.
  45. */
  46. asmlinkage int (*original_call)(const char *, int, int);
  47. /* The function we will replace sys_open (the function called when you
  48. * call the open system call) with. To find the exact prototype, with
  49. * the number and type of arguments, we find the original function first
  50. * (it is at fs/open.c).
  51. *
  52. * In theory, this means that we are tied to the current version of the
  53. * kernel. In practice, the system calls almost never change (it would
  54. * wreck havoc and require programs to be recompiled, since the system
  55. * calls are the interface between the kernel and the processes).
  56. */
  57. asmlinkage int our_sys_open(const char *filename, int flags, int mode)
  58. {
  59. int i = 0;
  60. char ch;
  61. /* Report the file, if relevant */
  62. pr_info("Opened file by %d: ", uid);
  63. do {
  64. get_user(ch, filename + i);
  65. i++;
  66. pr_info("%c", ch);
  67. } while (ch != 0);
  68. pr_info("\n");
  69. /* Call the original sys_open - otherwise, we lose the ability to
  70. * open files.
  71. */
  72. return original_call(filename, flags, mode);
  73. }
  74. static unsigned long **aquire_sys_call_table(void)
  75. {
  76. unsigned long int offset = PAGE_OFFSET;
  77. unsigned long **sct;
  78. while (offset < ULLONG_MAX) {
  79. sct = (unsigned long **) offset;
  80. if (sct[__NR_close] == (unsigned long *) close_fd)
  81. return sct;
  82. offset += sizeof(void *);
  83. }
  84. return NULL;
  85. }
  86. static int __init syscall_start(void)
  87. {
  88. if (!(sys_call_table = aquire_sys_call_table()))
  89. return -1;
  90. original_cr0 = read_cr0();
  91. write_cr0(original_cr0 & ~0x00010000);
  92. /* keep track of the original open function */
  93. original_call = (void *) sys_call_table[__NR_open];
  94. /* use our open function instead */
  95. sys_call_table[__NR_open] = (unsigned long *) our_sys_open;
  96. write_cr0(original_cr0);
  97. pr_info("Spying on UID:%d\n", uid);
  98. return 0;
  99. }
  100. static void __exit syscall_end(void)
  101. {
  102. if (!sys_call_table)
  103. return;
  104. /* Return the system call back to normal */
  105. if (sys_call_table[__NR_open] != (unsigned long *) our_sys_open) {
  106. pr_alert("Somebody else also played with the ");
  107. pr_alert("open system call\n");
  108. pr_alert("The system may be left in ");
  109. pr_alert("an unstable state.\n");
  110. }
  111. write_cr0(original_cr0 & ~0x00010000);
  112. sys_call_table[__NR_open] = (unsigned long *) original_call;
  113. write_cr0(original_cr0);
  114. msleep(2000);
  115. }
  116. module_init(syscall_start);
  117. module_exit(syscall_end);
  118. MODULE_LICENSE("GPL");