lkdtm_heap.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * This is for all the tests relating directly to heap memory, including
  3. * page allocation and slab allocations.
  4. */
  5. #include "lkdtm.h"
  6. #include <linux/slab.h>
  7. /*
  8. * This tries to stay within the next largest power-of-2 kmalloc cache
  9. * to avoid actually overwriting anything important if it's not detected
  10. * correctly.
  11. */
  12. void lkdtm_OVERWRITE_ALLOCATION(void)
  13. {
  14. size_t len = 1020;
  15. u32 *data = kmalloc(len, GFP_KERNEL);
  16. data[1024 / sizeof(u32)] = 0x12345678;
  17. kfree(data);
  18. }
  19. void lkdtm_WRITE_AFTER_FREE(void)
  20. {
  21. int *base, *again;
  22. size_t len = 1024;
  23. /*
  24. * The slub allocator uses the first word to store the free
  25. * pointer in some configurations. Use the middle of the
  26. * allocation to avoid running into the freelist
  27. */
  28. size_t offset = (len / sizeof(*base)) / 2;
  29. base = kmalloc(len, GFP_KERNEL);
  30. pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);
  31. pr_info("Attempting bad write to freed memory at %p\n",
  32. &base[offset]);
  33. kfree(base);
  34. base[offset] = 0x0abcdef0;
  35. /* Attempt to notice the overwrite. */
  36. again = kmalloc(len, GFP_KERNEL);
  37. kfree(again);
  38. if (again != base)
  39. pr_info("Hmm, didn't get the same memory range.\n");
  40. }
  41. void lkdtm_READ_AFTER_FREE(void)
  42. {
  43. int *base, *val, saw;
  44. size_t len = 1024;
  45. /*
  46. * The slub allocator uses the first word to store the free
  47. * pointer in some configurations. Use the middle of the
  48. * allocation to avoid running into the freelist
  49. */
  50. size_t offset = (len / sizeof(*base)) / 2;
  51. base = kmalloc(len, GFP_KERNEL);
  52. if (!base) {
  53. pr_info("Unable to allocate base memory.\n");
  54. return;
  55. }
  56. val = kmalloc(len, GFP_KERNEL);
  57. if (!val) {
  58. pr_info("Unable to allocate val memory.\n");
  59. kfree(base);
  60. return;
  61. }
  62. *val = 0x12345678;
  63. base[offset] = *val;
  64. pr_info("Value in memory before free: %x\n", base[offset]);
  65. kfree(base);
  66. pr_info("Attempting bad read from freed memory\n");
  67. saw = base[offset];
  68. if (saw != *val) {
  69. /* Good! Poisoning happened, so declare a win. */
  70. pr_info("Memory correctly poisoned (%x)\n", saw);
  71. BUG();
  72. }
  73. pr_info("Memory was not poisoned\n");
  74. kfree(val);
  75. }
  76. void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
  77. {
  78. unsigned long p = __get_free_page(GFP_KERNEL);
  79. if (!p) {
  80. pr_info("Unable to allocate free page\n");
  81. return;
  82. }
  83. pr_info("Writing to the buddy page before free\n");
  84. memset((void *)p, 0x3, PAGE_SIZE);
  85. free_page(p);
  86. schedule();
  87. pr_info("Attempting bad write to the buddy page after free\n");
  88. memset((void *)p, 0x78, PAGE_SIZE);
  89. /* Attempt to notice the overwrite. */
  90. p = __get_free_page(GFP_KERNEL);
  91. free_page(p);
  92. schedule();
  93. }
  94. void lkdtm_READ_BUDDY_AFTER_FREE(void)
  95. {
  96. unsigned long p = __get_free_page(GFP_KERNEL);
  97. int saw, *val;
  98. int *base;
  99. if (!p) {
  100. pr_info("Unable to allocate free page\n");
  101. return;
  102. }
  103. val = kmalloc(1024, GFP_KERNEL);
  104. if (!val) {
  105. pr_info("Unable to allocate val memory.\n");
  106. free_page(p);
  107. return;
  108. }
  109. base = (int *)p;
  110. *val = 0x12345678;
  111. base[0] = *val;
  112. pr_info("Value in memory before free: %x\n", base[0]);
  113. free_page(p);
  114. pr_info("Attempting to read from freed memory\n");
  115. saw = base[0];
  116. if (saw != *val) {
  117. /* Good! Poisoning happened, so declare a win. */
  118. pr_info("Memory correctly poisoned (%x)\n", saw);
  119. BUG();
  120. }
  121. pr_info("Buddy page was not poisoned\n");
  122. kfree(val);
  123. }