heap.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. if (!data)
  19. return;
  20. data[1024 / sizeof(u32)] = 0x12345678;
  21. kfree(data);
  22. }
  23. void lkdtm_WRITE_AFTER_FREE(void)
  24. {
  25. int *base, *again;
  26. size_t len = 1024;
  27. /*
  28. * The slub allocator uses the first word to store the free
  29. * pointer in some configurations. Use the middle of the
  30. * allocation to avoid running into the freelist
  31. */
  32. size_t offset = (len / sizeof(*base)) / 2;
  33. base = kmalloc(len, GFP_KERNEL);
  34. if (!base)
  35. return;
  36. pr_info("Allocated memory %p-%p\n", base, &base[offset * 2]);
  37. pr_info("Attempting bad write to freed memory at %p\n",
  38. &base[offset]);
  39. kfree(base);
  40. base[offset] = 0x0abcdef0;
  41. /* Attempt to notice the overwrite. */
  42. again = kmalloc(len, GFP_KERNEL);
  43. kfree(again);
  44. if (again != base)
  45. pr_info("Hmm, didn't get the same memory range.\n");
  46. }
  47. void lkdtm_READ_AFTER_FREE(void)
  48. {
  49. int *base, *val, saw;
  50. size_t len = 1024;
  51. /*
  52. * The slub allocator uses the first word to store the free
  53. * pointer in some configurations. Use the middle of the
  54. * allocation to avoid running into the freelist
  55. */
  56. size_t offset = (len / sizeof(*base)) / 2;
  57. base = kmalloc(len, GFP_KERNEL);
  58. if (!base) {
  59. pr_info("Unable to allocate base memory.\n");
  60. return;
  61. }
  62. val = kmalloc(len, GFP_KERNEL);
  63. if (!val) {
  64. pr_info("Unable to allocate val memory.\n");
  65. kfree(base);
  66. return;
  67. }
  68. *val = 0x12345678;
  69. base[offset] = *val;
  70. pr_info("Value in memory before free: %x\n", base[offset]);
  71. kfree(base);
  72. pr_info("Attempting bad read from freed memory\n");
  73. saw = base[offset];
  74. if (saw != *val) {
  75. /* Good! Poisoning happened, so declare a win. */
  76. pr_info("Memory correctly poisoned (%x)\n", saw);
  77. BUG();
  78. }
  79. pr_info("Memory was not poisoned\n");
  80. kfree(val);
  81. }
  82. void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
  83. {
  84. unsigned long p = __get_free_page(GFP_KERNEL);
  85. if (!p) {
  86. pr_info("Unable to allocate free page\n");
  87. return;
  88. }
  89. pr_info("Writing to the buddy page before free\n");
  90. memset((void *)p, 0x3, PAGE_SIZE);
  91. free_page(p);
  92. schedule();
  93. pr_info("Attempting bad write to the buddy page after free\n");
  94. memset((void *)p, 0x78, PAGE_SIZE);
  95. /* Attempt to notice the overwrite. */
  96. p = __get_free_page(GFP_KERNEL);
  97. free_page(p);
  98. schedule();
  99. }
  100. void lkdtm_READ_BUDDY_AFTER_FREE(void)
  101. {
  102. unsigned long p = __get_free_page(GFP_KERNEL);
  103. int saw, *val;
  104. int *base;
  105. if (!p) {
  106. pr_info("Unable to allocate free page\n");
  107. return;
  108. }
  109. val = kmalloc(1024, GFP_KERNEL);
  110. if (!val) {
  111. pr_info("Unable to allocate val memory.\n");
  112. free_page(p);
  113. return;
  114. }
  115. base = (int *)p;
  116. *val = 0x12345678;
  117. base[0] = *val;
  118. pr_info("Value in memory before free: %x\n", base[0]);
  119. free_page(p);
  120. pr_info("Attempting to read from freed memory\n");
  121. saw = base[0];
  122. if (saw != *val) {
  123. /* Good! Poisoning happened, so declare a win. */
  124. pr_info("Memory correctly poisoned (%x)\n", saw);
  125. BUG();
  126. }
  127. pr_info("Buddy page was not poisoned\n");
  128. kfree(val);
  129. }