mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] LoongArch: restore KFENCE pages through DMW on resume
@ 2026-10-31 13:21 Mike Rapoport (Microsoft)
  2026-11-08  7:59 ` Mike Rapoport
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Rapoport (Microsoft) @ 2026-10-31 13:21 UTC (permalink / raw)
  To: Huacai Chen; +Cc: Mike Rapoport, WANG Xuerui, linux-kernel, loongarch, stable

With KFENCE enabled, resume from hibernation triggers KFENCE reports while
swsusp_asm_resume() copies the image pages, for example:

  BUG: KFENCE: use-after-free write in swsusp_asm_resume+0x20/0x94

  Use-after-free write at 0x00000000a57ee925 (in kfence-#254):
   swsusp_asm_resume+0x20/0x94
   hibernation_restore+0x128/0x1a0
   load_image_and_restore+0x6c/0xc8
   software_resume+0x240/0x260
   do_one_initcall+0x68/0x200
   kernel_init_freeable+0x26c/0x304
   kernel_init+0x20/0x134
   ret_from_kernel_thread+0x24/0x1d0
   ret_from_kernel_thread_asm+0xc/0x98

During resume from hibernation, the image pages that occupy physical pages
used by the restore kernel are first loaded into free pages and then, as
the very last step, swsusp_asm_resume() copies them to their final location
pointed to by pbe->orig_address, which the hibernation core sets to
page_address() of the page in the restore kernel.

The early KFENCE pool is allocated from memblock and normally occupies the
same physical pages in the restore kernel and in the image kernel, so these
pages are usually copied by swsusp_asm_resume().

The KFENCE pool is remapped into the KFENCE area above vm_map_base and
set_page_address() adjusts page->virtual so that page_address() returns
the page-table mapped alias rather than the DMW address of the pool pages.

Hence, pbe->orig_address of KFENCE pages points to that alias and
swsusp_asm_resume() writes them through the page tables. But:

* the copy loop overwrites the kernel page tables, so a TLB refill for the
  KFENCE alias may use a partially restored page table
* the KFENCE pool pages that are protected in the restore kernel fault in
  the middle of the copy

Convert pbe->orig_address to DMW addresses before starting the copy.

Fixes: 0ca84aeaee15 ("LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE")
Cc: stable@vger.kernel.org
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
Reproduced with hibernation in QEMU, the KFENCE reports are gone with
this patch.
---
 arch/loongarch/power/hibernate.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/loongarch/power/hibernate.c b/arch/loongarch/power/hibernate.c
index 817270410ef98..ff571ab4e8df9 100644
--- a/arch/loongarch/power/hibernate.c
+++ b/arch/loongarch/power/hibernate.c
@@ -59,6 +59,18 @@ extern int swsusp_asm_resume(void);
 
 int swsusp_arch_resume(void)
 {
+	struct pbe *pbe;
+
+	/*
+	 * page_address() of KFENCE pages is mapped by page tables that are
+	 * overwritten during restore and may be protected by KFENCE, copy
+	 * through DMW instead.
+	 */
+	if (IS_ENABLED(CONFIG_KFENCE)) {
+		for (pbe = restore_pblist; pbe; pbe = pbe->next)
+			pbe->orig_address = __va(virt_to_phys(pbe->orig_address));
+	}
+
 	/* Avoid TLB mismatch during and after kernel resume */
 	local_flush_tlb_all();
 	return swsusp_asm_resume();

---
base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
change-id: 20261027-fixes-loongarch-fd3755f33919

--
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] LoongArch: restore KFENCE pages through DMW on resume
  2026-10-31 13:21 [PATCH] LoongArch: restore KFENCE pages through DMW on resume Mike Rapoport (Microsoft)
@ 2026-11-08  7:59 ` Mike Rapoport
  2026-11-08  8:17   ` Huacai Chen
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Rapoport @ 2026-11-08  7:59 UTC (permalink / raw)
  To: Huacai Chen; +Cc: WANG Xuerui, linux-kernel, loongarch, stable

Gentle ping :)

On Sat, Oct 31, 2026 at 03:21:46PM +0200, Mike Rapoport (Microsoft) wrote:
> With KFENCE enabled, resume from hibernation triggers KFENCE reports while
> swsusp_asm_resume() copies the image pages, for example:
> 
>   BUG: KFENCE: use-after-free write in swsusp_asm_resume+0x20/0x94
> 
>   Use-after-free write at 0x00000000a57ee925 (in kfence-#254):
>    swsusp_asm_resume+0x20/0x94
>    hibernation_restore+0x128/0x1a0
>    load_image_and_restore+0x6c/0xc8
>    software_resume+0x240/0x260
>    do_one_initcall+0x68/0x200
>    kernel_init_freeable+0x26c/0x304
>    kernel_init+0x20/0x134
>    ret_from_kernel_thread+0x24/0x1d0
>    ret_from_kernel_thread_asm+0xc/0x98
> 
> During resume from hibernation, the image pages that occupy physical pages
> used by the restore kernel are first loaded into free pages and then, as
> the very last step, swsusp_asm_resume() copies them to their final location
> pointed to by pbe->orig_address, which the hibernation core sets to
> page_address() of the page in the restore kernel.
> 
> The early KFENCE pool is allocated from memblock and normally occupies the
> same physical pages in the restore kernel and in the image kernel, so these
> pages are usually copied by swsusp_asm_resume().
> 
> The KFENCE pool is remapped into the KFENCE area above vm_map_base and
> set_page_address() adjusts page->virtual so that page_address() returns
> the page-table mapped alias rather than the DMW address of the pool pages.
> 
> Hence, pbe->orig_address of KFENCE pages points to that alias and
> swsusp_asm_resume() writes them through the page tables. But:
> 
> * the copy loop overwrites the kernel page tables, so a TLB refill for the
>   KFENCE alias may use a partially restored page table
> * the KFENCE pool pages that are protected in the restore kernel fault in
>   the middle of the copy
> 
> Convert pbe->orig_address to DMW addresses before starting the copy.
> 
> Fixes: 0ca84aeaee15 ("LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE")
> Cc: stable@vger.kernel.org
> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> ---
> Reproduced with hibernation in QEMU, the KFENCE reports are gone with
> this patch.
> ---
>  arch/loongarch/power/hibernate.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/loongarch/power/hibernate.c b/arch/loongarch/power/hibernate.c
> index 817270410ef98..ff571ab4e8df9 100644
> --- a/arch/loongarch/power/hibernate.c
> +++ b/arch/loongarch/power/hibernate.c
> @@ -59,6 +59,18 @@ extern int swsusp_asm_resume(void);
>  
>  int swsusp_arch_resume(void)
>  {
> +	struct pbe *pbe;
> +
> +	/*
> +	 * page_address() of KFENCE pages is mapped by page tables that are
> +	 * overwritten during restore and may be protected by KFENCE, copy
> +	 * through DMW instead.
> +	 */
> +	if (IS_ENABLED(CONFIG_KFENCE)) {
> +		for (pbe = restore_pblist; pbe; pbe = pbe->next)
> +			pbe->orig_address = __va(virt_to_phys(pbe->orig_address));
> +	}
> +
>  	/* Avoid TLB mismatch during and after kernel resume */
>  	local_flush_tlb_all();
>  	return swsusp_asm_resume();
> 
> ---
> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
> change-id: 20261027-fixes-loongarch-fd3755f33919
> 
> --
> Sincerely yours,
> Mike.
> 

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] LoongArch: restore KFENCE pages through DMW on resume
  2026-11-08  7:59 ` Mike Rapoport
@ 2026-11-08  8:17   ` Huacai Chen
  0 siblings, 0 replies; 3+ messages in thread
From: Huacai Chen @ 2026-11-08  8:17 UTC (permalink / raw)
  To: Mike Rapoport; +Cc: WANG Xuerui, linux-kernel, loongarch, stable

On Sun, Nov 8, 2026 at 3:59 PM Mike Rapoport <rppt@kernel.org> wrote:
>
> Gentle ping :)
Sorry for the late response, would you mind if I modify it to use
#ifdef? Usually it should be avoided, but I want to signal users that
KFENCE is not a usually enabled feature.

Huacai

>
> On Sat, Oct 31, 2026 at 03:21:46PM +0200, Mike Rapoport (Microsoft) wrote:
> > With KFENCE enabled, resume from hibernation triggers KFENCE reports while
> > swsusp_asm_resume() copies the image pages, for example:
> >
> >   BUG: KFENCE: use-after-free write in swsusp_asm_resume+0x20/0x94
> >
> >   Use-after-free write at 0x00000000a57ee925 (in kfence-#254):
> >    swsusp_asm_resume+0x20/0x94
> >    hibernation_restore+0x128/0x1a0
> >    load_image_and_restore+0x6c/0xc8
> >    software_resume+0x240/0x260
> >    do_one_initcall+0x68/0x200
> >    kernel_init_freeable+0x26c/0x304
> >    kernel_init+0x20/0x134
> >    ret_from_kernel_thread+0x24/0x1d0
> >    ret_from_kernel_thread_asm+0xc/0x98
> >
> > During resume from hibernation, the image pages that occupy physical pages
> > used by the restore kernel are first loaded into free pages and then, as
> > the very last step, swsusp_asm_resume() copies them to their final location
> > pointed to by pbe->orig_address, which the hibernation core sets to
> > page_address() of the page in the restore kernel.
> >
> > The early KFENCE pool is allocated from memblock and normally occupies the
> > same physical pages in the restore kernel and in the image kernel, so these
> > pages are usually copied by swsusp_asm_resume().
> >
> > The KFENCE pool is remapped into the KFENCE area above vm_map_base and
> > set_page_address() adjusts page->virtual so that page_address() returns
> > the page-table mapped alias rather than the DMW address of the pool pages.
> >
> > Hence, pbe->orig_address of KFENCE pages points to that alias and
> > swsusp_asm_resume() writes them through the page tables. But:
> >
> > * the copy loop overwrites the kernel page tables, so a TLB refill for the
> >   KFENCE alias may use a partially restored page table
> > * the KFENCE pool pages that are protected in the restore kernel fault in
> >   the middle of the copy
> >
> > Convert pbe->orig_address to DMW addresses before starting the copy.
> >
> > Fixes: 0ca84aeaee15 ("LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> > ---
> > Reproduced with hibernation in QEMU, the KFENCE reports are gone with
> > this patch.
> > ---
> >  arch/loongarch/power/hibernate.c | 12 ++++++++++++
> >  1 file changed, 12 insertions(+)
> >
> > diff --git a/arch/loongarch/power/hibernate.c b/arch/loongarch/power/hibernate.c
> > index 817270410ef98..ff571ab4e8df9 100644
> > --- a/arch/loongarch/power/hibernate.c
> > +++ b/arch/loongarch/power/hibernate.c
> > @@ -59,6 +59,18 @@ extern int swsusp_asm_resume(void);
> >
> >  int swsusp_arch_resume(void)
> >  {
> > +     struct pbe *pbe;
> > +
> > +     /*
> > +      * page_address() of KFENCE pages is mapped by page tables that are
> > +      * overwritten during restore and may be protected by KFENCE, copy
> > +      * through DMW instead.
> > +      */
> > +     if (IS_ENABLED(CONFIG_KFENCE)) {
> > +             for (pbe = restore_pblist; pbe; pbe = pbe->next)
> > +                     pbe->orig_address = __va(virt_to_phys(pbe->orig_address));
> > +     }
> > +
> >       /* Avoid TLB mismatch during and after kernel resume */
> >       local_flush_tlb_all();
> >       return swsusp_asm_resume();
> >
> > ---
> > base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
> > change-id: 20261027-fixes-loongarch-fd3755f33919
> >
> > --
> > Sincerely yours,
> > Mike.
> >
>
> --
> Sincerely yours,
> Mike.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-08  8:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-31 13:21 [PATCH] LoongArch: restore KFENCE pages through DMW on resume Mike Rapoport (Microsoft)
2026-11-08  7:59 ` Mike Rapoport
2026-11-08  8:17   ` Huacai Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®