1313
1414static pgd_t kasan_pg_dir [PTRS_PER_PGD ] __initdata __aligned (PAGE_SIZE );
1515
16+ #ifdef __PAGETABLE_P4D_FOLDED
17+ #define __pgd_none (early , pgd ) (0)
18+ #else
19+ #define __pgd_none (early , pgd ) (early ? (pgd_val(pgd) == 0) : \
20+ (__pa(pgd_val(pgd)) == (unsigned long)__pa(kasan_early_shadow_p4d)))
21+ #endif
22+
1623#ifdef __PAGETABLE_PUD_FOLDED
1724#define __p4d_none (early , p4d ) (0)
1825#else
@@ -55,6 +62,9 @@ void *kasan_mem_to_shadow(const void *addr)
5562 case XKPRANGE_UC_SEG :
5663 offset = XKPRANGE_UC_SHADOW_OFFSET ;
5764 break ;
65+ case XKPRANGE_WC_SEG :
66+ offset = XKPRANGE_WC_SHADOW_OFFSET ;
67+ break ;
5868 case XKVRANGE_VC_SEG :
5969 offset = XKVRANGE_VC_SHADOW_OFFSET ;
6070 break ;
@@ -79,6 +89,8 @@ const void *kasan_shadow_to_mem(const void *shadow_addr)
7989
8090 if (addr >= XKVRANGE_VC_SHADOW_OFFSET )
8191 return (void * )(((addr - XKVRANGE_VC_SHADOW_OFFSET ) << KASAN_SHADOW_SCALE_SHIFT ) + XKVRANGE_VC_START );
92+ else if (addr >= XKPRANGE_WC_SHADOW_OFFSET )
93+ return (void * )(((addr - XKPRANGE_WC_SHADOW_OFFSET ) << KASAN_SHADOW_SCALE_SHIFT ) + XKPRANGE_WC_START );
8294 else if (addr >= XKPRANGE_UC_SHADOW_OFFSET )
8395 return (void * )(((addr - XKPRANGE_UC_SHADOW_OFFSET ) << KASAN_SHADOW_SCALE_SHIFT ) + XKPRANGE_UC_START );
8496 else if (addr >= XKPRANGE_CC_SHADOW_OFFSET )
@@ -142,6 +154,19 @@ static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node,
142154 return pud_offset (p4dp , addr );
143155}
144156
157+ static p4d_t * __init kasan_p4d_offset (pgd_t * pgdp , unsigned long addr , int node , bool early )
158+ {
159+ if (__pgd_none (early , pgdp_get (pgdp ))) {
160+ phys_addr_t p4d_phys = early ?
161+ __pa_symbol (kasan_early_shadow_p4d ) : kasan_alloc_zeroed_page (node );
162+ if (!early )
163+ memcpy (__va (p4d_phys ), kasan_early_shadow_p4d , sizeof (kasan_early_shadow_p4d ));
164+ pgd_populate (& init_mm , pgdp , (p4d_t * )__va (p4d_phys ));
165+ }
166+
167+ return p4d_offset (pgdp , addr );
168+ }
169+
145170static void __init kasan_pte_populate (pmd_t * pmdp , unsigned long addr ,
146171 unsigned long end , int node , bool early )
147172{
@@ -178,19 +203,19 @@ static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr,
178203 do {
179204 next = pud_addr_end (addr , end );
180205 kasan_pmd_populate (pudp , addr , next , node , early );
181- } while (pudp ++ , addr = next , addr != end );
206+ } while (pudp ++ , addr = next , addr != end && __pud_none ( early , READ_ONCE ( * pudp )) );
182207}
183208
184209static void __init kasan_p4d_populate (pgd_t * pgdp , unsigned long addr ,
185210 unsigned long end , int node , bool early )
186211{
187212 unsigned long next ;
188- p4d_t * p4dp = p4d_offset (pgdp , addr );
213+ p4d_t * p4dp = kasan_p4d_offset (pgdp , addr , node , early );
189214
190215 do {
191216 next = p4d_addr_end (addr , end );
192217 kasan_pud_populate (p4dp , addr , next , node , early );
193- } while (p4dp ++ , addr = next , addr != end );
218+ } while (p4dp ++ , addr = next , addr != end && __p4d_none ( early , READ_ONCE ( * p4dp )) );
194219}
195220
196221static void __init kasan_pgd_populate (unsigned long addr , unsigned long end ,
@@ -218,7 +243,7 @@ static void __init kasan_map_populate(unsigned long start, unsigned long end,
218243asmlinkage void __init kasan_early_init (void )
219244{
220245 BUILD_BUG_ON (!IS_ALIGNED (KASAN_SHADOW_START , PGDIR_SIZE ));
221- BUILD_BUG_ON (!IS_ALIGNED (KASAN_SHADOW_END , PGDIR_SIZE ));
246+ BUILD_BUG_ON (!IS_ALIGNED (KASAN_SHADOW_END + 1 , PGDIR_SIZE ));
222247}
223248
224249static inline void kasan_set_pgd (pgd_t * pgdp , pgd_t pgdval )
@@ -233,7 +258,7 @@ static void __init clear_pgds(unsigned long start, unsigned long end)
233258 * swapper_pg_dir. pgd_clear() can't be used
234259 * here because it's nop on 2,3-level pagetable setups
235260 */
236- for (; start < end ; start += PGDIR_SIZE )
261+ for (; start < end ; start = pgd_addr_end ( start , end ) )
237262 kasan_set_pgd ((pgd_t * )pgd_offset_k (start ), __pgd (0 ));
238263}
239264
@@ -242,6 +267,17 @@ void __init kasan_init(void)
242267 u64 i ;
243268 phys_addr_t pa_start , pa_end ;
244269
270+ /*
271+ * If PGDIR_SIZE is too large for cpu_vabits, KASAN_SHADOW_END will
272+ * overflow UINTPTR_MAX and then looks like a user space address.
273+ * For example, PGDIR_SIZE of CONFIG_4KB_4LEVEL is 2^39, which is too
274+ * large for Loongson-2K series whose cpu_vabits = 39.
275+ */
276+ if (KASAN_SHADOW_END < vm_map_base ) {
277+ pr_warn ("PGDIR_SIZE too large for cpu_vabits, KernelAddressSanitizer disabled.\n" );
278+ return ;
279+ }
280+
245281 /*
246282 * PGD was populated as invalid_pmd_table or invalid_pud_table
247283 * in pagetable_init() which depends on how many levels of page
0 commit comments