Commit 56531761 authored by David Hildenbrand's avatar David Hildenbrand Committed by Andrew Morton
Browse files

kfence: drop nth_page() usage

We want to get rid of nth_page(), and kfence init code is the last user.

Unfortunately, we might actually walk a PFN range where the pages are not
contiguous, because we might be allocating an area from memblock that
could span memory sections in problematic kernel configs (SPARSEMEM
without SPARSEMEM_VMEMMAP).

We could check whether the page range is contiguous using
page_range_contiguous() and failing kfence init, or making kfence
incompatible these problemtic kernel configs.

Let's keep it simple and simply use pfn_to_page() by iterating PFNs.

Link: https://lkml.kernel.org/r/20250901150359.867252-36-david@redhat.com


Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarMarco Elver <elver@google.com>
Reviewed-by: default avatarLorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent b5ba761a
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -594,15 +594,14 @@ static void rcu_guarded_free(struct rcu_head *h)
 */
static unsigned long kfence_init_pool(void)
{
	unsigned long addr;
	struct page *pages;
	unsigned long addr, start_pfn;
	int i;

	if (!arch_kfence_init_pool())
		return (unsigned long)__kfence_pool;

	addr = (unsigned long)__kfence_pool;
	pages = virt_to_page(__kfence_pool);
	start_pfn = PHYS_PFN(virt_to_phys(__kfence_pool));

	/*
	 * Set up object pages: they must have PGTY_slab set to avoid freeing
@@ -613,11 +612,12 @@ static unsigned long kfence_init_pool(void)
	 * enters __slab_free() slow-path.
	 */
	for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
		struct slab *slab = page_slab(nth_page(pages, i));
		struct slab *slab;

		if (!i || (i % 2))
			continue;

		slab = page_slab(pfn_to_page(start_pfn + i));
		__folio_set_slab(slab_folio(slab));
#ifdef CONFIG_MEMCG
		slab->obj_exts = (unsigned long)&kfence_metadata_init[i / 2 - 1].obj_exts |
@@ -665,10 +665,12 @@ static unsigned long kfence_init_pool(void)

reset_slab:
	for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
		struct slab *slab = page_slab(nth_page(pages, i));
		struct slab *slab;

		if (!i || (i % 2))
			continue;

		slab = page_slab(pfn_to_page(start_pfn + i));
#ifdef CONFIG_MEMCG
		slab->obj_exts = 0;
#endif