lkdtm_heap.c 3.3 KB

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