root/mm/kasan/init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kasan_p4d_table
  2. kasan_p4d_table
  3. kasan_pud_table
  4. kasan_pud_table
  5. kasan_pmd_table
  6. kasan_pmd_table
  7. kasan_pte_table
  8. kasan_early_shadow_page_entry
  9. early_alloc
  10. zero_pte_populate
  11. zero_pmd_populate
  12. zero_pud_populate
  13. zero_p4d_populate
  14. kasan_populate_early_shadow
  15. kasan_free_pte
  16. kasan_free_pmd
  17. kasan_free_pud
  18. kasan_free_p4d
  19. kasan_remove_pte_table
  20. kasan_remove_pmd_table
  21. kasan_remove_pud_table
  22. kasan_remove_p4d_table
  23. kasan_remove_zero_shadow
  24. kasan_add_zero_shadow

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * This file contains some kasan initialization code.
   4  *
   5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
   6  * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
   7  *
   8  * This program is free software; you can redistribute it and/or modify
   9  * it under the terms of the GNU General Public License version 2 as
  10  * published by the Free Software Foundation.
  11  *
  12  */
  13 
  14 #include <linux/memblock.h>
  15 #include <linux/init.h>
  16 #include <linux/kasan.h>
  17 #include <linux/kernel.h>
  18 #include <linux/mm.h>
  19 #include <linux/pfn.h>
  20 #include <linux/slab.h>
  21 
  22 #include <asm/page.h>
  23 #include <asm/pgalloc.h>
  24 
  25 #include "kasan.h"
  26 
  27 /*
  28  * This page serves two purposes:
  29  *   - It used as early shadow memory. The entire shadow region populated
  30  *     with this page, before we will be able to setup normal shadow memory.
  31  *   - Latter it reused it as zero shadow to cover large ranges of memory
  32  *     that allowed to access, but not handled by kasan (vmalloc/vmemmap ...).
  33  */
  34 unsigned char kasan_early_shadow_page[PAGE_SIZE] __page_aligned_bss;
  35 
  36 #if CONFIG_PGTABLE_LEVELS > 4
  37 p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D] __page_aligned_bss;
  38 static inline bool kasan_p4d_table(pgd_t pgd)
  39 {
  40         return pgd_page(pgd) == virt_to_page(lm_alias(kasan_early_shadow_p4d));
  41 }
  42 #else
  43 static inline bool kasan_p4d_table(pgd_t pgd)
  44 {
  45         return false;
  46 }
  47 #endif
  48 #if CONFIG_PGTABLE_LEVELS > 3
  49 pud_t kasan_early_shadow_pud[PTRS_PER_PUD] __page_aligned_bss;
  50 static inline bool kasan_pud_table(p4d_t p4d)
  51 {
  52         return p4d_page(p4d) == virt_to_page(lm_alias(kasan_early_shadow_pud));
  53 }
  54 #else
  55 static inline bool kasan_pud_table(p4d_t p4d)
  56 {
  57         return false;
  58 }
  59 #endif
  60 #if CONFIG_PGTABLE_LEVELS > 2
  61 pmd_t kasan_early_shadow_pmd[PTRS_PER_PMD] __page_aligned_bss;
  62 static inline bool kasan_pmd_table(pud_t pud)
  63 {
  64         return pud_page(pud) == virt_to_page(lm_alias(kasan_early_shadow_pmd));
  65 }
  66 #else
  67 static inline bool kasan_pmd_table(pud_t pud)
  68 {
  69         return false;
  70 }
  71 #endif
  72 pte_t kasan_early_shadow_pte[PTRS_PER_PTE] __page_aligned_bss;
  73 
  74 static inline bool kasan_pte_table(pmd_t pmd)
  75 {
  76         return pmd_page(pmd) == virt_to_page(lm_alias(kasan_early_shadow_pte));
  77 }
  78 
  79 static inline bool kasan_early_shadow_page_entry(pte_t pte)
  80 {
  81         return pte_page(pte) == virt_to_page(lm_alias(kasan_early_shadow_page));
  82 }
  83 
  84 static __init void *early_alloc(size_t size, int node)
  85 {
  86         void *ptr = memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
  87                                            MEMBLOCK_ALLOC_ACCESSIBLE, node);
  88 
  89         if (!ptr)
  90                 panic("%s: Failed to allocate %zu bytes align=%zx nid=%d from=%llx\n",
  91                       __func__, size, size, node, (u64)__pa(MAX_DMA_ADDRESS));
  92 
  93         return ptr;
  94 }
  95 
  96 static void __ref zero_pte_populate(pmd_t *pmd, unsigned long addr,
  97                                 unsigned long end)
  98 {
  99         pte_t *pte = pte_offset_kernel(pmd, addr);
 100         pte_t zero_pte;
 101 
 102         zero_pte = pfn_pte(PFN_DOWN(__pa_symbol(kasan_early_shadow_page)),
 103                                 PAGE_KERNEL);
 104         zero_pte = pte_wrprotect(zero_pte);
 105 
 106         while (addr + PAGE_SIZE <= end) {
 107                 set_pte_at(&init_mm, addr, pte, zero_pte);
 108                 addr += PAGE_SIZE;
 109                 pte = pte_offset_kernel(pmd, addr);
 110         }
 111 }
 112 
 113 static int __ref zero_pmd_populate(pud_t *pud, unsigned long addr,
 114                                 unsigned long end)
 115 {
 116         pmd_t *pmd = pmd_offset(pud, addr);
 117         unsigned long next;
 118 
 119         do {
 120                 next = pmd_addr_end(addr, end);
 121 
 122                 if (IS_ALIGNED(addr, PMD_SIZE) && end - addr >= PMD_SIZE) {
 123                         pmd_populate_kernel(&init_mm, pmd,
 124                                         lm_alias(kasan_early_shadow_pte));
 125                         continue;
 126                 }
 127 
 128                 if (pmd_none(*pmd)) {
 129                         pte_t *p;
 130 
 131                         if (slab_is_available())
 132                                 p = pte_alloc_one_kernel(&init_mm);
 133                         else
 134                                 p = early_alloc(PAGE_SIZE, NUMA_NO_NODE);
 135                         if (!p)
 136                                 return -ENOMEM;
 137 
 138                         pmd_populate_kernel(&init_mm, pmd, p);
 139                 }
 140                 zero_pte_populate(pmd, addr, next);
 141         } while (pmd++, addr = next, addr != end);
 142 
 143         return 0;
 144 }
 145 
 146 static int __ref zero_pud_populate(p4d_t *p4d, unsigned long addr,
 147                                 unsigned long end)
 148 {
 149         pud_t *pud = pud_offset(p4d, addr);
 150         unsigned long next;
 151 
 152         do {
 153                 next = pud_addr_end(addr, end);
 154                 if (IS_ALIGNED(addr, PUD_SIZE) && end - addr >= PUD_SIZE) {
 155                         pmd_t *pmd;
 156 
 157                         pud_populate(&init_mm, pud,
 158                                         lm_alias(kasan_early_shadow_pmd));
 159                         pmd = pmd_offset(pud, addr);
 160                         pmd_populate_kernel(&init_mm, pmd,
 161                                         lm_alias(kasan_early_shadow_pte));
 162                         continue;
 163                 }
 164 
 165                 if (pud_none(*pud)) {
 166                         pmd_t *p;
 167 
 168                         if (slab_is_available()) {
 169                                 p = pmd_alloc(&init_mm, pud, addr);
 170                                 if (!p)
 171                                         return -ENOMEM;
 172                         } else {
 173                                 pud_populate(&init_mm, pud,
 174                                         early_alloc(PAGE_SIZE, NUMA_NO_NODE));
 175                         }
 176                 }
 177                 zero_pmd_populate(pud, addr, next);
 178         } while (pud++, addr = next, addr != end);
 179 
 180         return 0;
 181 }
 182 
 183 static int __ref zero_p4d_populate(pgd_t *pgd, unsigned long addr,
 184                                 unsigned long end)
 185 {
 186         p4d_t *p4d = p4d_offset(pgd, addr);
 187         unsigned long next;
 188 
 189         do {
 190                 next = p4d_addr_end(addr, end);
 191                 if (IS_ALIGNED(addr, P4D_SIZE) && end - addr >= P4D_SIZE) {
 192                         pud_t *pud;
 193                         pmd_t *pmd;
 194 
 195                         p4d_populate(&init_mm, p4d,
 196                                         lm_alias(kasan_early_shadow_pud));
 197                         pud = pud_offset(p4d, addr);
 198                         pud_populate(&init_mm, pud,
 199                                         lm_alias(kasan_early_shadow_pmd));
 200                         pmd = pmd_offset(pud, addr);
 201                         pmd_populate_kernel(&init_mm, pmd,
 202                                         lm_alias(kasan_early_shadow_pte));
 203                         continue;
 204                 }
 205 
 206                 if (p4d_none(*p4d)) {
 207                         pud_t *p;
 208 
 209                         if (slab_is_available()) {
 210                                 p = pud_alloc(&init_mm, p4d, addr);
 211                                 if (!p)
 212                                         return -ENOMEM;
 213                         } else {
 214                                 p4d_populate(&init_mm, p4d,
 215                                         early_alloc(PAGE_SIZE, NUMA_NO_NODE));
 216                         }
 217                 }
 218                 zero_pud_populate(p4d, addr, next);
 219         } while (p4d++, addr = next, addr != end);
 220 
 221         return 0;
 222 }
 223 
 224 /**
 225  * kasan_populate_early_shadow - populate shadow memory region with
 226  *                               kasan_early_shadow_page
 227  * @shadow_start - start of the memory range to populate
 228  * @shadow_end   - end of the memory range to populate
 229  */
 230 int __ref kasan_populate_early_shadow(const void *shadow_start,
 231                                         const void *shadow_end)
 232 {
 233         unsigned long addr = (unsigned long)shadow_start;
 234         unsigned long end = (unsigned long)shadow_end;
 235         pgd_t *pgd = pgd_offset_k(addr);
 236         unsigned long next;
 237 
 238         do {
 239                 next = pgd_addr_end(addr, end);
 240 
 241                 if (IS_ALIGNED(addr, PGDIR_SIZE) && end - addr >= PGDIR_SIZE) {
 242                         p4d_t *p4d;
 243                         pud_t *pud;
 244                         pmd_t *pmd;
 245 
 246                         /*
 247                          * kasan_early_shadow_pud should be populated with pmds
 248                          * at this moment.
 249                          * [pud,pmd]_populate*() below needed only for
 250                          * 3,2 - level page tables where we don't have
 251                          * puds,pmds, so pgd_populate(), pud_populate()
 252                          * is noops.
 253                          *
 254                          * The ifndef is required to avoid build breakage.
 255                          *
 256                          * With 5level-fixup.h, pgd_populate() is not nop and
 257                          * we reference kasan_early_shadow_p4d. It's not defined
 258                          * unless 5-level paging enabled.
 259                          *
 260                          * The ifndef can be dropped once all KASAN-enabled
 261                          * architectures will switch to pgtable-nop4d.h.
 262                          */
 263 #ifndef __ARCH_HAS_5LEVEL_HACK
 264                         pgd_populate(&init_mm, pgd,
 265                                         lm_alias(kasan_early_shadow_p4d));
 266 #endif
 267                         p4d = p4d_offset(pgd, addr);
 268                         p4d_populate(&init_mm, p4d,
 269                                         lm_alias(kasan_early_shadow_pud));
 270                         pud = pud_offset(p4d, addr);
 271                         pud_populate(&init_mm, pud,
 272                                         lm_alias(kasan_early_shadow_pmd));
 273                         pmd = pmd_offset(pud, addr);
 274                         pmd_populate_kernel(&init_mm, pmd,
 275                                         lm_alias(kasan_early_shadow_pte));
 276                         continue;
 277                 }
 278 
 279                 if (pgd_none(*pgd)) {
 280                         p4d_t *p;
 281 
 282                         if (slab_is_available()) {
 283                                 p = p4d_alloc(&init_mm, pgd, addr);
 284                                 if (!p)
 285                                         return -ENOMEM;
 286                         } else {
 287                                 pgd_populate(&init_mm, pgd,
 288                                         early_alloc(PAGE_SIZE, NUMA_NO_NODE));
 289                         }
 290                 }
 291                 zero_p4d_populate(pgd, addr, next);
 292         } while (pgd++, addr = next, addr != end);
 293 
 294         return 0;
 295 }
 296 
 297 static void kasan_free_pte(pte_t *pte_start, pmd_t *pmd)
 298 {
 299         pte_t *pte;
 300         int i;
 301 
 302         for (i = 0; i < PTRS_PER_PTE; i++) {
 303                 pte = pte_start + i;
 304                 if (!pte_none(*pte))
 305                         return;
 306         }
 307 
 308         pte_free_kernel(&init_mm, (pte_t *)page_to_virt(pmd_page(*pmd)));
 309         pmd_clear(pmd);
 310 }
 311 
 312 static void kasan_free_pmd(pmd_t *pmd_start, pud_t *pud)
 313 {
 314         pmd_t *pmd;
 315         int i;
 316 
 317         for (i = 0; i < PTRS_PER_PMD; i++) {
 318                 pmd = pmd_start + i;
 319                 if (!pmd_none(*pmd))
 320                         return;
 321         }
 322 
 323         pmd_free(&init_mm, (pmd_t *)page_to_virt(pud_page(*pud)));
 324         pud_clear(pud);
 325 }
 326 
 327 static void kasan_free_pud(pud_t *pud_start, p4d_t *p4d)
 328 {
 329         pud_t *pud;
 330         int i;
 331 
 332         for (i = 0; i < PTRS_PER_PUD; i++) {
 333                 pud = pud_start + i;
 334                 if (!pud_none(*pud))
 335                         return;
 336         }
 337 
 338         pud_free(&init_mm, (pud_t *)page_to_virt(p4d_page(*p4d)));
 339         p4d_clear(p4d);
 340 }
 341 
 342 static void kasan_free_p4d(p4d_t *p4d_start, pgd_t *pgd)
 343 {
 344         p4d_t *p4d;
 345         int i;
 346 
 347         for (i = 0; i < PTRS_PER_P4D; i++) {
 348                 p4d = p4d_start + i;
 349                 if (!p4d_none(*p4d))
 350                         return;
 351         }
 352 
 353         p4d_free(&init_mm, (p4d_t *)page_to_virt(pgd_page(*pgd)));
 354         pgd_clear(pgd);
 355 }
 356 
 357 static void kasan_remove_pte_table(pte_t *pte, unsigned long addr,
 358                                 unsigned long end)
 359 {
 360         unsigned long next;
 361 
 362         for (; addr < end; addr = next, pte++) {
 363                 next = (addr + PAGE_SIZE) & PAGE_MASK;
 364                 if (next > end)
 365                         next = end;
 366 
 367                 if (!pte_present(*pte))
 368                         continue;
 369 
 370                 if (WARN_ON(!kasan_early_shadow_page_entry(*pte)))
 371                         continue;
 372                 pte_clear(&init_mm, addr, pte);
 373         }
 374 }
 375 
 376 static void kasan_remove_pmd_table(pmd_t *pmd, unsigned long addr,
 377                                 unsigned long end)
 378 {
 379         unsigned long next;
 380 
 381         for (; addr < end; addr = next, pmd++) {
 382                 pte_t *pte;
 383 
 384                 next = pmd_addr_end(addr, end);
 385 
 386                 if (!pmd_present(*pmd))
 387                         continue;
 388 
 389                 if (kasan_pte_table(*pmd)) {
 390                         if (IS_ALIGNED(addr, PMD_SIZE) &&
 391                             IS_ALIGNED(next, PMD_SIZE))
 392                                 pmd_clear(pmd);
 393                         continue;
 394                 }
 395                 pte = pte_offset_kernel(pmd, addr);
 396                 kasan_remove_pte_table(pte, addr, next);
 397                 kasan_free_pte(pte_offset_kernel(pmd, 0), pmd);
 398         }
 399 }
 400 
 401 static void kasan_remove_pud_table(pud_t *pud, unsigned long addr,
 402                                 unsigned long end)
 403 {
 404         unsigned long next;
 405 
 406         for (; addr < end; addr = next, pud++) {
 407                 pmd_t *pmd, *pmd_base;
 408 
 409                 next = pud_addr_end(addr, end);
 410 
 411                 if (!pud_present(*pud))
 412                         continue;
 413 
 414                 if (kasan_pmd_table(*pud)) {
 415                         if (IS_ALIGNED(addr, PUD_SIZE) &&
 416                             IS_ALIGNED(next, PUD_SIZE))
 417                                 pud_clear(pud);
 418                         continue;
 419                 }
 420                 pmd = pmd_offset(pud, addr);
 421                 pmd_base = pmd_offset(pud, 0);
 422                 kasan_remove_pmd_table(pmd, addr, next);
 423                 kasan_free_pmd(pmd_base, pud);
 424         }
 425 }
 426 
 427 static void kasan_remove_p4d_table(p4d_t *p4d, unsigned long addr,
 428                                 unsigned long end)
 429 {
 430         unsigned long next;
 431 
 432         for (; addr < end; addr = next, p4d++) {
 433                 pud_t *pud;
 434 
 435                 next = p4d_addr_end(addr, end);
 436 
 437                 if (!p4d_present(*p4d))
 438                         continue;
 439 
 440                 if (kasan_pud_table(*p4d)) {
 441                         if (IS_ALIGNED(addr, P4D_SIZE) &&
 442                             IS_ALIGNED(next, P4D_SIZE))
 443                                 p4d_clear(p4d);
 444                         continue;
 445                 }
 446                 pud = pud_offset(p4d, addr);
 447                 kasan_remove_pud_table(pud, addr, next);
 448                 kasan_free_pud(pud_offset(p4d, 0), p4d);
 449         }
 450 }
 451 
 452 void kasan_remove_zero_shadow(void *start, unsigned long size)
 453 {
 454         unsigned long addr, end, next;
 455         pgd_t *pgd;
 456 
 457         addr = (unsigned long)kasan_mem_to_shadow(start);
 458         end = addr + (size >> KASAN_SHADOW_SCALE_SHIFT);
 459 
 460         if (WARN_ON((unsigned long)start %
 461                         (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)) ||
 462             WARN_ON(size % (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)))
 463                 return;
 464 
 465         for (; addr < end; addr = next) {
 466                 p4d_t *p4d;
 467 
 468                 next = pgd_addr_end(addr, end);
 469 
 470                 pgd = pgd_offset_k(addr);
 471                 if (!pgd_present(*pgd))
 472                         continue;
 473 
 474                 if (kasan_p4d_table(*pgd)) {
 475                         if (IS_ALIGNED(addr, PGDIR_SIZE) &&
 476                             IS_ALIGNED(next, PGDIR_SIZE))
 477                                 pgd_clear(pgd);
 478                         continue;
 479                 }
 480 
 481                 p4d = p4d_offset(pgd, addr);
 482                 kasan_remove_p4d_table(p4d, addr, next);
 483                 kasan_free_p4d(p4d_offset(pgd, 0), pgd);
 484         }
 485 }
 486 
 487 int kasan_add_zero_shadow(void *start, unsigned long size)
 488 {
 489         int ret;
 490         void *shadow_start, *shadow_end;
 491 
 492         shadow_start = kasan_mem_to_shadow(start);
 493         shadow_end = shadow_start + (size >> KASAN_SHADOW_SCALE_SHIFT);
 494 
 495         if (WARN_ON((unsigned long)start %
 496                         (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)) ||
 497             WARN_ON(size % (KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE)))
 498                 return -EINVAL;
 499 
 500         ret = kasan_populate_early_shadow(shadow_start, shadow_end);
 501         if (ret)
 502                 kasan_remove_zero_shadow(shadow_start,
 503                                         size >> KASAN_SHADOW_SCALE_SHIFT);
 504         return ret;
 505 }

/* [<][>][^][v][top][bottom][index][help] */