shadow.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include <linux/kmemcheck.h>
  2. #include <linux/module.h>
  3. #include <linux/mm.h>
  4. #include <asm/page.h>
  5. #include <asm/pgtable.h>
  6. #include "pte.h"
  7. #include "shadow.h"
  8. /*
  9. * Return the shadow address for the given address. Returns NULL if the
  10. * address is not tracked.
  11. *
  12. * We need to be extremely careful not to follow any invalid pointers,
  13. * because this function can be called for *any* possible address.
  14. */
  15. void *kmemcheck_shadow_lookup(unsigned long address)
  16. {
  17. pte_t *pte;
  18. struct page *page;
  19. if (!virt_addr_valid(address))
  20. return NULL;
  21. pte = kmemcheck_pte_lookup(address);
  22. if (!pte)
  23. return NULL;
  24. page = virt_to_page(address);
  25. if (!page->shadow)
  26. return NULL;
  27. return page->shadow + (address & (PAGE_SIZE - 1));
  28. }
  29. static void mark_shadow(void *address, unsigned int n,
  30. enum kmemcheck_shadow status)
  31. {
  32. unsigned long addr = (unsigned long) address;
  33. unsigned long last_addr = addr + n - 1;
  34. unsigned long page = addr & PAGE_MASK;
  35. unsigned long last_page = last_addr & PAGE_MASK;
  36. unsigned int first_n;
  37. void *shadow;
  38. /* If the memory range crosses a page boundary, stop there. */
  39. if (page == last_page)
  40. first_n = n;
  41. else
  42. first_n = page + PAGE_SIZE - addr;
  43. shadow = kmemcheck_shadow_lookup(addr);
  44. if (shadow)
  45. memset(shadow, status, first_n);
  46. addr += first_n;
  47. n -= first_n;
  48. /* Do full-page memset()s. */
  49. while (n >= PAGE_SIZE) {
  50. shadow = kmemcheck_shadow_lookup(addr);
  51. if (shadow)
  52. memset(shadow, status, PAGE_SIZE);
  53. addr += PAGE_SIZE;
  54. n -= PAGE_SIZE;
  55. }
  56. /* Do the remaining page, if any. */
  57. if (n > 0) {
  58. shadow = kmemcheck_shadow_lookup(addr);
  59. if (shadow)
  60. memset(shadow, status, n);
  61. }
  62. }
  63. void kmemcheck_mark_unallocated(void *address, unsigned int n)
  64. {
  65. mark_shadow(address, n, KMEMCHECK_SHADOW_UNALLOCATED);
  66. }
  67. void kmemcheck_mark_uninitialized(void *address, unsigned int n)
  68. {
  69. mark_shadow(address, n, KMEMCHECK_SHADOW_UNINITIALIZED);
  70. }
  71. /*
  72. * Fill the shadow memory of the given address such that the memory at that
  73. * address is marked as being initialized.
  74. */
  75. void kmemcheck_mark_initialized(void *address, unsigned int n)
  76. {
  77. mark_shadow(address, n, KMEMCHECK_SHADOW_INITIALIZED);
  78. }
  79. EXPORT_SYMBOL_GPL(kmemcheck_mark_initialized);
  80. void kmemcheck_mark_freed(void *address, unsigned int n)
  81. {
  82. mark_shadow(address, n, KMEMCHECK_SHADOW_FREED);
  83. }
  84. void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n)
  85. {
  86. unsigned int i;
  87. for (i = 0; i < n; ++i)
  88. kmemcheck_mark_unallocated(page_address(&p[i]), PAGE_SIZE);
  89. }
  90. void kmemcheck_mark_uninitialized_pages(struct page *p, unsigned int n)
  91. {
  92. unsigned int i;
  93. for (i = 0; i < n; ++i)
  94. kmemcheck_mark_uninitialized(page_address(&p[i]), PAGE_SIZE);
  95. }
  96. void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n)
  97. {
  98. unsigned int i;
  99. for (i = 0; i < n; ++i)
  100. kmemcheck_mark_initialized(page_address(&p[i]), PAGE_SIZE);
  101. }
  102. enum kmemcheck_shadow kmemcheck_shadow_test(void *shadow, unsigned int size)
  103. {
  104. uint8_t *x;
  105. unsigned int i;
  106. x = shadow;
  107. #ifdef CONFIG_KMEMCHECK_PARTIAL_OK
  108. /*
  109. * Make sure _some_ bytes are initialized. Gcc frequently generates
  110. * code to access neighboring bytes.
  111. */
  112. for (i = 0; i < size; ++i) {
  113. if (x[i] == KMEMCHECK_SHADOW_INITIALIZED)
  114. return x[i];
  115. }
  116. #else
  117. /* All bytes must be initialized. */
  118. for (i = 0; i < size; ++i) {
  119. if (x[i] != KMEMCHECK_SHADOW_INITIALIZED)
  120. return x[i];
  121. }
  122. #endif
  123. return x[0];
  124. }
  125. void kmemcheck_shadow_set(void *shadow, unsigned int size)
  126. {
  127. uint8_t *x;
  128. unsigned int i;
  129. x = shadow;
  130. for (i = 0; i < size; ++i)
  131. x[i] = KMEMCHECK_SHADOW_INITIALIZED;
  132. }