@@ -96,7 +96,7 @@ static unsigned long kfence_skip_covered_thresh __read_mostly = 75;
9696module_param_named (skip_covered_thresh , kfence_skip_covered_thresh , ulong , 0644 );
9797
9898/* The pool of pages used for guard pages and objects. */
99- char * __kfence_pool __ro_after_init ;
99+ char * __kfence_pool __read_mostly ;
100100EXPORT_SYMBOL (__kfence_pool ); /* Export for test modules. */
101101
102102/*
@@ -537,17 +537,19 @@ static void rcu_guarded_free(struct rcu_head *h)
537537 kfence_guarded_free ((void * )meta -> addr , meta , false);
538538}
539539
540- static bool __init kfence_init_pool (void )
540+ /*
541+ * Initialization of the KFENCE pool after its allocation.
542+ * Returns 0 on success; otherwise returns the address up to
543+ * which partial initialization succeeded.
544+ */
545+ static unsigned long kfence_init_pool (void )
541546{
542547 unsigned long addr = (unsigned long )__kfence_pool ;
543548 struct page * pages ;
544549 int i ;
545550
546- if (!__kfence_pool )
547- return false;
548-
549551 if (!arch_kfence_init_pool ())
550- goto err ;
552+ return addr ;
551553
552554 pages = virt_to_page (addr );
553555
@@ -565,7 +567,7 @@ static bool __init kfence_init_pool(void)
565567
566568 /* Verify we do not have a compound head page. */
567569 if (WARN_ON (compound_head (& pages [i ]) != & pages [i ]))
568- goto err ;
570+ return addr ;
569571
570572 __SetPageSlab (& pages [i ]);
571573 }
@@ -578,7 +580,7 @@ static bool __init kfence_init_pool(void)
578580 */
579581 for (i = 0 ; i < 2 ; i ++ ) {
580582 if (unlikely (!kfence_protect (addr )))
581- goto err ;
583+ return addr ;
582584
583585 addr += PAGE_SIZE ;
584586 }
@@ -595,7 +597,7 @@ static bool __init kfence_init_pool(void)
595597
596598 /* Protect the right redzone. */
597599 if (unlikely (!kfence_protect (addr + PAGE_SIZE )))
598- goto err ;
600+ return addr ;
599601
600602 addr += 2 * PAGE_SIZE ;
601603 }
@@ -608,9 +610,21 @@ static bool __init kfence_init_pool(void)
608610 */
609611 kmemleak_free (__kfence_pool );
610612
611- return true;
613+ return 0 ;
614+ }
615+
616+ static bool __init kfence_init_pool_early (void )
617+ {
618+ unsigned long addr ;
619+
620+ if (!__kfence_pool )
621+ return false;
622+
623+ addr = kfence_init_pool ();
624+
625+ if (!addr )
626+ return true;
612627
613- err :
614628 /*
615629 * Only release unprotected pages, and do not try to go back and change
616630 * page attributes due to risk of failing to do so as well. If changing
@@ -623,6 +637,26 @@ static bool __init kfence_init_pool(void)
623637 return false;
624638}
625639
640+ static bool kfence_init_pool_late (void )
641+ {
642+ unsigned long addr , free_size ;
643+
644+ addr = kfence_init_pool ();
645+
646+ if (!addr )
647+ return true;
648+
649+ /* Same as above. */
650+ free_size = KFENCE_POOL_SIZE - (addr - (unsigned long )__kfence_pool );
651+ #ifdef CONFIG_CONTIG_ALLOC
652+ free_contig_range (page_to_pfn (virt_to_page (addr )), free_size / PAGE_SIZE );
653+ #else
654+ free_pages_exact ((void * )addr , free_size );
655+ #endif
656+ __kfence_pool = NULL ;
657+ return false;
658+ }
659+
626660/* === DebugFS Interface ==================================================== */
627661
628662static int stats_show (struct seq_file * seq , void * v )
@@ -771,31 +805,66 @@ void __init kfence_alloc_pool(void)
771805 pr_err ("failed to allocate pool\n" );
772806}
773807
808+ static void kfence_init_enable (void )
809+ {
810+ if (!IS_ENABLED (CONFIG_KFENCE_STATIC_KEYS ))
811+ static_branch_enable (& kfence_allocation_key );
812+ WRITE_ONCE (kfence_enabled , true);
813+ queue_delayed_work (system_unbound_wq , & kfence_timer , 0 );
814+ pr_info ("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n" , KFENCE_POOL_SIZE ,
815+ CONFIG_KFENCE_NUM_OBJECTS , (void * )__kfence_pool ,
816+ (void * )(__kfence_pool + KFENCE_POOL_SIZE ));
817+ }
818+
774819void __init kfence_init (void )
775820{
821+ stack_hash_seed = (u32 )random_get_entropy ();
822+
776823 /* Setting kfence_sample_interval to 0 on boot disables KFENCE. */
777824 if (!kfence_sample_interval )
778825 return ;
779826
780- stack_hash_seed = (u32 )random_get_entropy ();
781- if (!kfence_init_pool ()) {
827+ if (!kfence_init_pool_early ()) {
782828 pr_err ("%s failed\n" , __func__ );
783829 return ;
784830 }
785831
786- if (!IS_ENABLED (CONFIG_KFENCE_STATIC_KEYS ))
787- static_branch_enable (& kfence_allocation_key );
788- WRITE_ONCE (kfence_enabled , true);
789- queue_delayed_work (system_unbound_wq , & kfence_timer , 0 );
790- pr_info ("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n" , KFENCE_POOL_SIZE ,
791- CONFIG_KFENCE_NUM_OBJECTS , (void * )__kfence_pool ,
792- (void * )(__kfence_pool + KFENCE_POOL_SIZE ));
832+ kfence_init_enable ();
833+ }
834+
835+ static int kfence_init_late (void )
836+ {
837+ const unsigned long nr_pages = KFENCE_POOL_SIZE / PAGE_SIZE ;
838+ #ifdef CONFIG_CONTIG_ALLOC
839+ struct page * pages ;
840+
841+ pages = alloc_contig_pages (nr_pages , GFP_KERNEL , first_online_node , NULL );
842+ if (!pages )
843+ return - ENOMEM ;
844+ __kfence_pool = page_to_virt (pages );
845+ #else
846+ if (nr_pages > MAX_ORDER_NR_PAGES ) {
847+ pr_warn ("KFENCE_NUM_OBJECTS too large for buddy allocator\n" );
848+ return - EINVAL ;
849+ }
850+ __kfence_pool = alloc_pages_exact (KFENCE_POOL_SIZE , GFP_KERNEL );
851+ if (!__kfence_pool )
852+ return - ENOMEM ;
853+ #endif
854+
855+ if (!kfence_init_pool_late ()) {
856+ pr_err ("%s failed\n" , __func__ );
857+ return - EBUSY ;
858+ }
859+
860+ kfence_init_enable ();
861+ return 0 ;
793862}
794863
795864static int kfence_enable_late (void )
796865{
797866 if (!__kfence_pool )
798- return - EINVAL ;
867+ return kfence_init_late () ;
799868
800869 WRITE_ONCE (kfence_enabled , true);
801870 queue_delayed_work (system_unbound_wq , & kfence_timer , 0 );
0 commit comments