mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache
@ 2026-10-01 13:22 Frédéric MARIE-JOSEPH
  2026-10-01 15:24 ` Dave Hansen
  0 siblings, 1 reply; 5+ messages in thread
From: Frédéric MARIE-JOSEPH @ 2026-10-01 13:22 UTC (permalink / raw)
  To: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen
  Cc: H. Peter Anvin, Peter Zijlstra, Mike Rapoport, linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 1743 bytes --]

Hello to list,

That's my first post so I hope I do things right. I found what seems to me
like a bug, and worked with Claude to find a patch. Hope it will be usefull.

With CONFIG_MODULES=n there is no STRICT_MODULE_RWX, so x86 does not
select ARCH_HAS_EXECMEM_ROX and execmem_restore_rox() is the stub that
returns 0. its_pages_protect() relies on it alone, so the dynamic ITS
thunk pages, made executable by set_memory_x() in its_alloc(), stay
writable and executable for the life of the kernel. CONFIG_DEBUG_WX
reports them on every boot:

  x86/mm: Checked W+X mappings: FAILED, 7 W+X pages found.

The attached patch makes the pages read-only with set_memory_ro() when
the ROX cache is not built; when it is, nothing changes.

Tested on a CONFIG_MODULES=n x86_64 build of 6.18.53 booted under
QEMU/KVM: with the change, the boots report "x86/mm: Checked W+X
mappings: passed, no W+X pages found." and no warning. On mainline
(551c722f4), whose its_pages_protect() is identical,
arch/x86/kernel/alternative.o builds without warnings with that
configuration and with x86_64_defconfig; mainline itself was not booted.

The bug was found, and the fix and its message written, with the help
of an AI coding assistant (Claude, Anthropic), and reviewed by me.

The patch is attached in git format-patch form (my mail client would
damage it inline); it applies with "git am". I can resend it inline
with git send-email if you prefer.

Fixes: a82b26451de1 ("x86/its: explicitly manage permissions for ITS pages")

Regards,
Frederic MARIE-JOSEPH



Frédéric MARIE-JOSEPH

*N° TVA intracommunautaire FR78788461903*
*N° SIRET 78846190300015/78846190300023*
*fmjconsulting.fr <http://fmjconsulting.fr>*

[-- Attachment #1.2: Type: text/html, Size: 2964 bytes --]

[-- Attachment #2: 0001-x86-its-Make-ITS-thunk-pages-read-only-without-the-R.patch --]
[-- Type: text/x-patch, Size: 2471 bytes --]

From ca4f1442f2f29de770fd23b66ac3ccc3f9295722 Mon Sep 17 00:00:00 2001
From: Frederic MARIE-JOSEPH <fredericmariejoseph@gmail.com>
Date: Thu, 1 Oct 2026 15:00:00 +0200
Subject: [PATCH] x86/its: Make ITS thunk pages read-only without the ROX
 execmem cache

With CONFIG_MODULES=n there is no STRICT_MODULE_RWX, so x86 does not
select ARCH_HAS_EXECMEM_ROX and execmem_restore_rox() is the stub that
returns 0. its_pages_protect() relies on it alone, so the dynamic ITS
thunk pages, made executable by set_memory_x() in its_alloc(), stay
writable and executable for the life of the kernel. CONFIG_DEBUG_WX
reports them on every boot:

  x86/mm: Checked W+X mappings: FAILED, 7 W+X pages found.

Make the pages read-only with set_memory_ro() when the ROX cache is not
built. When it is, nothing changes.

Found by the W+X check of a CONFIG_MODULES=n x86_64 build of 6.18.53
booted under QEMU/KVM. Tested on that build only: with the change, both
boots of the test report "x86/mm: Checked W+X mappings: passed, no W+X
pages found." and no warning. On mainline, whose its_pages_protect() is
identical, arch/x86/kernel/alternative.o builds without warnings with that
CONFIG_MODULES=n configuration and with x86_64_defconfig (modules and the
ROX cache on, where the IS_ENABLED() branch keeps the current call);
mainline itself was not booted.

The bug was found, and the fix and this message written, with the help
of an AI coding assistant (Claude, Anthropic), and reviewed by me.

Fixes: a82b26451de1 ("x86/its: explicitly manage permissions for ITS pages")
Assisted-by: LLM
Signed-off-by: Frederic MARIE-JOSEPH <fredericmariejoseph@gmail.com>
---
 arch/x86/kernel/alternative.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 582c6d830..ad08ac9b1 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -168,7 +168,15 @@ static void its_pages_protect(struct its_array *pages)
 {
 	for (int i = 0; i < pages->num; i++) {
 		void *page = pages->pages[i];
-		execmem_restore_rox(page, PAGE_SIZE);
+		/*
+		 * Without the ROX execmem cache (no STRICT_MODULE_RWX, so no
+		 * modules) execmem_restore_rox() is a stub and the thunk pages
+		 * would stay writable and executable: make them read-only.
+		 */
+		if (IS_ENABLED(CONFIG_ARCH_HAS_EXECMEM_ROX))
+			execmem_restore_rox(page, PAGE_SIZE);
+		else
+			set_memory_ro((unsigned long)page, 1);
 	}
 }
 

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

* Re: [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache
  2026-10-01 13:22 [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache Frédéric MARIE-JOSEPH
@ 2026-10-01 15:24 ` Dave Hansen
  2026-10-01 16:38   ` Frédéric MARIE-JOSEPH
  2026-10-02 17:52   ` Mike Rapoport
  0 siblings, 2 replies; 5+ messages in thread
From: Dave Hansen @ 2026-10-01 15:24 UTC (permalink / raw)
  To: Frédéric MARIE-JOSEPH, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen
  Cc: H. Peter Anvin, Peter Zijlstra, Mike Rapoport, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1448 bytes --]

On 10/1/26 06:22, Frédéric MARIE-JOSEPH wrote:
> That's my first post so I hope I do things right. I found what seems to
> me like a bug, and worked with Claude to find a patch. Hope it will be
> usefull.

Your mailer is sending out HTML, but there was a plain-text version too,
so the message at least made it to the archives. Using git-send-email is
the most foolproof way to send these things, fwiw.

> With CONFIG_MODULES=n there is no STRICT_MODULE_RWX, so x86 does not
> select ARCH_HAS_EXECMEM_ROX and execmem_restore_rox() is the stub that
> returns 0.

Ugh. The origin of this seems to be:

         select ARCH_HAS_EXECMEM_ROX             if X86_64 &&
STRICT_MODULE_RWX
from:

> commit 47410d839fcda6890cb82828f874f97710982f24
> Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
> Date:   Tue Jun 3 14:14:42 2025 +0300
> 
>     x86/Kconfig: only enable ROX cache in execmem when STRICT_MODULE_RWX is set

That commit is trying to change execmem internal details via an
arch-specific Kconfig tweak. It's also logically a bit silly that what
an arch supports:

	ARCH_HAS_EXECMEM_ROX

depends on a module-specific option:

	STRICT_MODULE_RWX

If execmem is being too aggressive on for modules on !STRICT_MODULE_RWX
configs, shouldn't the fix be in execmem *module* code?

Maybe something along the line of the lightly-tested attached patch? I
see the "11 W+X pages found" message without it, and the message goes
away when it is applied.

[-- Attachment #2: x86-STRICT_MODULE_RWX.patch --]
[-- Type: text/x-patch, Size: 1232 bytes --]



---

 b/arch/x86/Kconfig     |    2 +-
 b/kernel/module/main.c |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff -puN arch/x86/Kconfig~x86-STRICT_MODULE_RWX arch/x86/Kconfig
--- a/arch/x86/Kconfig~x86-STRICT_MODULE_RWX	2026-10-01 06:31:14.379577124 -0700
+++ b/arch/x86/Kconfig	2026-10-01 06:31:39.777436090 -0700
@@ -85,7 +85,7 @@ config X86
 	select ARCH_HAS_DMA_OPS			if GART_IOMMU || XEN
 	select ARCH_HAS_EARLY_DEBUG		if KGDB
 	select ARCH_HAS_ELF_RANDOMIZE
-	select ARCH_HAS_EXECMEM_ROX		if X86_64 && STRICT_MODULE_RWX
+	select ARCH_HAS_EXECMEM_ROX		if X86_64
 	select ARCH_HAS_FAST_MULTIPLIER
 	select ARCH_HAS_FORTIFY_SOURCE
 	select ARCH_HAS_GCOV_PROFILE_ALL
diff -puN kernel/module/main.c~x86-STRICT_MODULE_RWX kernel/module/main.c
--- a/kernel/module/main.c~x86-STRICT_MODULE_RWX	2026-10-01 06:44:42.417795788 -0700
+++ b/kernel/module/main.c	2026-10-01 06:51:28.048722976 -0700
@@ -1355,7 +1355,8 @@ static int module_memory_alloc(struct mo
 	if (!ptr)
 		return -ENOMEM;
 
-	mod->mem[type].is_rox = execmem_is_rox(execmem_type);
+	if (IS_ENABLED(STRICT_MODULE_RWX))
+		mod->mem[type].is_rox = execmem_is_rox(execmem_type);
 
 	/*
 	 * The pointer to these blocks of memory are stored on the module
_

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

* Re: [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache
  2026-10-01 15:24 ` Dave Hansen
@ 2026-10-01 16:38   ` Frédéric MARIE-JOSEPH
  2026-10-02 17:52   ` Mike Rapoport
  1 sibling, 0 replies; 5+ messages in thread
From: Frédéric MARIE-JOSEPH @ 2026-10-01 16:38 UTC (permalink / raw)
  To: Dave Hansen
  Cc: x86, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
	H. Peter Anvin, Peter Zijlstra, Mike Rapoport, linux-kernel

On 10/1/26 08:24, Dave Hansen wrote:
> Your mailer is sending out HTML, but there was a plain-text version too,
> so the message at least made it to the archives. Using git-send-email is
> the most foolproof way to send these things, fwiw.

Thanks, noted. I'll try to use git send-email next time.

> If execmem is being too aggressive on for modules on !STRICT_MODULE_RWX
> configs, shouldn't the fix be in execmem *module* code?

Ok I see. Better to fix it at the root cause rather than in its_pages_protect().

One thing in the attached patch, which Claude noticed and I didn't,
probably a typo:

> +    if (IS_ENABLED(STRICT_MODULE_RWX))

IS_ENABLED() takes the full symbol name, so this should be
IS_ENABLED(CONFIG_STRICT_MODULE_RWX). As written it is always 0.

In my config (CONFIG_MODULES=n, 6.18.53, ITS mitigation active under
KVM) only the Kconfig hunk is built. I tested your patch instead of
mine. Every boot reports
"x86/mm: Checked W+X mappings: passed, no W+X pages found." (it reported
7 W+X pages before), and our boot tests (kselftests, LKDTM,
kernel-hardening-checker) still pass. Thank you for your quick review.

Tested-by: Frederic MARIE-JOSEPH <fredericmariejoseph@gmail.com>

Regards,
Frederic


Frédéric MARIE-JOSEPH
N° TVA intracommunautaire FR78788461903
N° SIRET 78846190300015/78846190300023
fmjconsulting.fr




Le jeu. 1 oct. 2026 à 17:24, Dave Hansen <dave.hansen@intel.com> a écrit :
>
> On 10/1/26 06:22, Frédéric MARIE-JOSEPH wrote:
> > That's my first post so I hope I do things right. I found what seems to
> > me like a bug, and worked with Claude to find a patch. Hope it will be
> > usefull.
>
> Your mailer is sending out HTML, but there was a plain-text version too,
> so the message at least made it to the archives. Using git-send-email is
> the most foolproof way to send these things, fwiw.
>
> > With CONFIG_MODULES=n there is no STRICT_MODULE_RWX, so x86 does not
> > select ARCH_HAS_EXECMEM_ROX and execmem_restore_rox() is the stub that
> > returns 0.
>
> Ugh. The origin of this seems to be:
>
>          select ARCH_HAS_EXECMEM_ROX             if X86_64 &&
> STRICT_MODULE_RWX
> from:
>
> > commit 47410d839fcda6890cb82828f874f97710982f24
> > Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
> > Date:   Tue Jun 3 14:14:42 2025 +0300
> >
> >     x86/Kconfig: only enable ROX cache in execmem when STRICT_MODULE_RWX is set
>
> That commit is trying to change execmem internal details via an
> arch-specific Kconfig tweak. It's also logically a bit silly that what
> an arch supports:
>
>         ARCH_HAS_EXECMEM_ROX
>
> depends on a module-specific option:
>
>         STRICT_MODULE_RWX
>
> If execmem is being too aggressive on for modules on !STRICT_MODULE_RWX
> configs, shouldn't the fix be in execmem *module* code?
>
> Maybe something along the line of the lightly-tested attached patch? I
> see the "11 W+X pages found" message without it, and the message goes
> away when it is applied.

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

* Re: [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache
  2026-10-01 15:24 ` Dave Hansen
  2026-10-01 16:38   ` Frédéric MARIE-JOSEPH
@ 2026-10-02 17:52   ` Mike Rapoport
  2026-10-02 17:58     ` Dave Hansen
  1 sibling, 1 reply; 5+ messages in thread
From: Mike Rapoport @ 2026-10-02 17:52 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Frédéric MARIE-JOSEPH, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Peter Zijlstra, linux-kernel

On Thu, Oct 01, 2026 at 08:24:50AM -0700, Dave Hansen wrote:
> On 10/1/26 06:22, Frédéric MARIE-JOSEPH wrote:
> > That's my first post so I hope I do things right. I found what seems to
> > me like a bug, and worked with Claude to find a patch. Hope it will be
> > usefull.
> 
> Your mailer is sending out HTML, but there was a plain-text version too,
> so the message at least made it to the archives. Using git-send-email is
> the most foolproof way to send these things, fwiw.
> 
> > With CONFIG_MODULES=n there is no STRICT_MODULE_RWX, so x86 does not
> > select ARCH_HAS_EXECMEM_ROX and execmem_restore_rox() is the stub that
> > returns 0.
> 
> Ugh. The origin of this seems to be:
> 
>          select ARCH_HAS_EXECMEM_ROX             if X86_64 &&
> STRICT_MODULE_RWX
> from:
> 
> > commit 47410d839fcda6890cb82828f874f97710982f24
> > Author: Mike Rapoport (Microsoft) <rppt@kernel.org>
> > Date:   Tue Jun 3 14:14:42 2025 +0300
> > 
> >     x86/Kconfig: only enable ROX cache in execmem when STRICT_MODULE_RWX is set
> 
> That commit is trying to change execmem internal details via an
> arch-specific Kconfig tweak. It's also logically a bit silly that what
> an arch supports:
> 
> 	ARCH_HAS_EXECMEM_ROX
> 
> depends on a module-specific option:
> 
> 	STRICT_MODULE_RWX
> 
> If execmem is being too aggressive on for modules on !STRICT_MODULE_RWX
> configs, shouldn't the fix be in execmem *module* code?

I think we can only have !STRICT_MODULE_RWX when MODULES=n, so it's not
because we are lax with modules code, but because there are no modules.

And since STRICT_KERNEL_RWX is always enabled on x86, I think we we want
ROX caches everywhere except Xen PV.

A while ago Richard send a patch that added STRICT_KERNEL_RWX to that
Kconfig dependency 

https://lore.kernel.org/all/20260625090627.1501095-1-richard@nod.at/

but apparently it fell between the cracks.

Since STRICT_MODULE_RWX || STRICT_KERNEL_RWX is always true, I'd say that
we can just revert 47410d839fcda, especially as I have hard time
remembering why I did it in the first place :)
 
> Maybe something along the line of the lightly-tested attached patch? I
> see the "11 W+X pages found" message without it, and the message goes
> away when it is applied.

> 
> 
> ---
> 
>  b/arch/x86/Kconfig     |    2 +-
>  b/kernel/module/main.c |    3 ++-
>  2 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff -puN arch/x86/Kconfig~x86-STRICT_MODULE_RWX arch/x86/Kconfig
> --- a/arch/x86/Kconfig~x86-STRICT_MODULE_RWX	2026-10-01 06:31:14.379577124 -0700
> +++ b/arch/x86/Kconfig	2026-10-01 06:31:39.777436090 -0700
> @@ -85,7 +85,7 @@ config X86
>  	select ARCH_HAS_DMA_OPS			if GART_IOMMU || XEN
>  	select ARCH_HAS_EARLY_DEBUG		if KGDB
>  	select ARCH_HAS_ELF_RANDOMIZE
> -	select ARCH_HAS_EXECMEM_ROX		if X86_64 && STRICT_MODULE_RWX
> +	select ARCH_HAS_EXECMEM_ROX		if X86_64
>  	select ARCH_HAS_FAST_MULTIPLIER
>  	select ARCH_HAS_FORTIFY_SOURCE
>  	select ARCH_HAS_GCOV_PROFILE_ALL
> diff -puN kernel/module/main.c~x86-STRICT_MODULE_RWX kernel/module/main.c
> --- a/kernel/module/main.c~x86-STRICT_MODULE_RWX	2026-10-01 06:44:42.417795788 -0700
> +++ b/kernel/module/main.c	2026-10-01 06:51:28.048722976 -0700
> @@ -1355,7 +1355,8 @@ static int module_memory_alloc(struct mo
>  	if (!ptr)
>  		return -ENOMEM;
>  
> -	mod->mem[type].is_rox = execmem_is_rox(execmem_type);
> +	if (IS_ENABLED(STRICT_MODULE_RWX))
> +		mod->mem[type].is_rox = execmem_is_rox(execmem_type);
>  
>  	/*
>  	 * The pointer to these blocks of memory are stored on the module
> _


-- 
Sincerely yours,
Mike.

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

* Re: [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache
  2026-10-02 17:52   ` Mike Rapoport
@ 2026-10-02 17:58     ` Dave Hansen
  0 siblings, 0 replies; 5+ messages in thread
From: Dave Hansen @ 2026-10-02 17:58 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Frédéric MARIE-JOSEPH, x86, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin,
	Peter Zijlstra, linux-kernel

On 10/2/26 10:52, Mike Rapoport wrote:
> Since STRICT_MODULE_RWX || STRICT_KERNEL_RWX is always true, I'd say that
> we can just revert 47410d839fcda, especially as I have hard time
> remembering why I did it in the first place 🙂

FWIW, that's what the LLMs were trying to convince me to do as well.

I'll put together a revert unless somebody beats me to it.

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

end of thread, other threads:[~2026-10-02 17:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01 13:22 [PATCH] x86/its: Make ITS thunk pages read-only without the ROX execmem cache Frédéric MARIE-JOSEPH
2026-10-01 15:24 ` Dave Hansen
2026-10-01 16:38   ` Frédéric MARIE-JOSEPH
2026-10-02 17:52   ` Mike Rapoport
2026-10-02 17:58     ` Dave Hansen

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®