kasan_init.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Xtensa KASAN shadow map initialization
  3. *
  4. * This file is subject to the terms and conditions of the GNU General Public
  5. * License. See the file "COPYING" in the main directory of this archive
  6. * for more details.
  7. *
  8. * Copyright (C) 2017 Cadence Design Systems Inc.
  9. */
  10. #include <linux/bootmem.h>
  11. #include <linux/init_task.h>
  12. #include <linux/kasan.h>
  13. #include <linux/kernel.h>
  14. #include <linux/memblock.h>
  15. #include <asm/initialize_mmu.h>
  16. #include <asm/tlbflush.h>
  17. #include <asm/traps.h>
  18. void __init kasan_early_init(void)
  19. {
  20. unsigned long vaddr = KASAN_SHADOW_START;
  21. pgd_t *pgd = pgd_offset_k(vaddr);
  22. pmd_t *pmd = pmd_offset(pgd, vaddr);
  23. int i;
  24. for (i = 0; i < PTRS_PER_PTE; ++i)
  25. set_pte(kasan_zero_pte + i,
  26. mk_pte(virt_to_page(kasan_zero_page), PAGE_KERNEL));
  27. for (vaddr = 0; vaddr < KASAN_SHADOW_SIZE; vaddr += PMD_SIZE, ++pmd) {
  28. BUG_ON(!pmd_none(*pmd));
  29. set_pmd(pmd, __pmd((unsigned long)kasan_zero_pte));
  30. }
  31. early_trap_init();
  32. }
  33. static void __init populate(void *start, void *end)
  34. {
  35. unsigned long n_pages = (end - start) / PAGE_SIZE;
  36. unsigned long n_pmds = n_pages / PTRS_PER_PTE;
  37. unsigned long i, j;
  38. unsigned long vaddr = (unsigned long)start;
  39. pgd_t *pgd = pgd_offset_k(vaddr);
  40. pmd_t *pmd = pmd_offset(pgd, vaddr);
  41. pte_t *pte = memblock_virt_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
  42. pr_debug("%s: %p - %p\n", __func__, start, end);
  43. for (i = j = 0; i < n_pmds; ++i) {
  44. int k;
  45. for (k = 0; k < PTRS_PER_PTE; ++k, ++j) {
  46. phys_addr_t phys =
  47. memblock_alloc_base(PAGE_SIZE, PAGE_SIZE,
  48. MEMBLOCK_ALLOC_ANYWHERE);
  49. set_pte(pte + j, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
  50. }
  51. }
  52. for (i = 0; i < n_pmds ; ++i, pte += PTRS_PER_PTE)
  53. set_pmd(pmd + i, __pmd((unsigned long)pte));
  54. local_flush_tlb_all();
  55. memset(start, 0, end - start);
  56. }
  57. void __init kasan_init(void)
  58. {
  59. int i;
  60. BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_START -
  61. (KASAN_START_VADDR >> KASAN_SHADOW_SCALE_SHIFT));
  62. BUILD_BUG_ON(VMALLOC_START < KASAN_START_VADDR);
  63. /*
  64. * Replace shadow map pages that cover addresses from VMALLOC area
  65. * start to the end of KSEG with clean writable pages.
  66. */
  67. populate(kasan_mem_to_shadow((void *)VMALLOC_START),
  68. kasan_mem_to_shadow((void *)XCHAL_KSEG_BYPASS_VADDR));
  69. /* Write protect kasan_zero_page and zero-initialize it again. */
  70. for (i = 0; i < PTRS_PER_PTE; ++i)
  71. set_pte(kasan_zero_pte + i,
  72. mk_pte(virt_to_page(kasan_zero_page), PAGE_KERNEL_RO));
  73. local_flush_tlb_all();
  74. memset(kasan_zero_page, 0, PAGE_SIZE);
  75. /* At this point kasan is fully initialized. Enable error messages. */
  76. current->kasan_depth = 0;
  77. pr_info("KernelAddressSanitizer initialized\n");
  78. }