syscall.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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/syscalls.h>
  17. #include <linux/unistd.h> /* The list of system calls */
  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. unsigned long **sys_call_table;
  24. unsigned long original_cr0;
  25. /* UID we want to spy on - will be filled from the command line. */
  26. static int uid;
  27. module_param(uid, int, 0644);
  28. /* A pointer to the original system call. The reason we keep this, rather
  29. * than call the original function (sys_open), is because somebody else
  30. * might have replaced the system call before us. Note that this is not
  31. * 100% safe, because if another module replaced sys_open before us,
  32. * then when we are inserted, we will call the function in that module -
  33. * and it might be removed before we are.
  34. *
  35. * Another reason for this is that we can not get sys_open.
  36. * It is a static variable, so it is not exported.
  37. */
  38. asmlinkage int (*original_call)(const char *, int, int);
  39. /* The function we will replace sys_open (the function called when you
  40. * call the open system call) with. To find the exact prototype, with
  41. * the number and type of arguments, we find the original function first
  42. * (it is at fs/open.c).
  43. *
  44. * In theory, this means that we are tied to the current version of the
  45. * kernel. In practice, the system calls almost never change (it would
  46. * wreck havoc and require programs to be recompiled, since the system
  47. * calls are the interface between the kernel and the processes).
  48. */
  49. asmlinkage int our_sys_open(const char *filename, int flags, int mode)
  50. {
  51. int i = 0;
  52. char ch;
  53. /* Report the file, if relevant */
  54. pr_info("Opened file by %d: ", uid);
  55. do {
  56. get_user(ch, filename + i);
  57. i++;
  58. pr_info("%c", ch);
  59. } while (ch != 0);
  60. pr_info("\n");
  61. /* Call the original sys_open - otherwise, we lose the ability to
  62. * open files.
  63. */
  64. return original_call(filename, flags, mode);
  65. }
  66. static unsigned long **aquire_sys_call_table(void)
  67. {
  68. unsigned long int offset = PAGE_OFFSET;
  69. unsigned long **sct;
  70. while (offset < ULLONG_MAX) {
  71. sct = (unsigned long **) offset;
  72. if (sct[__NR_close] == (unsigned long *) ksys_close)
  73. return sct;
  74. offset += sizeof(void *);
  75. }
  76. return NULL;
  77. }
  78. static int __init syscall_start(void)
  79. {
  80. if (!(sys_call_table = aquire_sys_call_table()))
  81. return -1;
  82. original_cr0 = read_cr0();
  83. write_cr0(original_cr0 & ~0x00010000);
  84. /* keep track of the original open function */
  85. original_call = (void *) sys_call_table[__NR_open];
  86. /* use our open function instead */
  87. sys_call_table[__NR_open] = (unsigned long *) our_sys_open;
  88. write_cr0(original_cr0);
  89. pr_info("Spying on UID:%d\n", uid);
  90. return 0;
  91. }
  92. static void __exit syscall_end(void)
  93. {
  94. if (!sys_call_table)
  95. return;
  96. /* Return the system call back to normal */
  97. if (sys_call_table[__NR_open] != (unsigned long *) our_sys_open) {
  98. pr_alert("Somebody else also played with the ");
  99. pr_alert("open system call\n");
  100. pr_alert("The system may be left in ");
  101. pr_alert("an unstable state.\n");
  102. }
  103. write_cr0(original_cr0 & ~0x00010000);
  104. sys_call_table[__NR_open] = (unsigned long *) original_call;
  105. write_cr0(original_cr0);
  106. msleep(2000);
  107. }
  108. module_init(syscall_start);
  109. module_exit(syscall_end);
  110. MODULE_LICENSE("GPL");