* [PATCH 0/3] x86: Fix some bugs related to ITS mitigation @ 2025-05-28 12:35 Juergen Gross 2025-05-28 12:35 ` [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages Juergen Gross ` (2 more replies) 0 siblings, 3 replies; 18+ messages in thread From: Juergen Gross @ 2025-05-28 12:35 UTC (permalink / raw) To: linux-kernel, x86 Cc: xin, Juergen Gross, Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, stable Running as a Xen PV guest uncovered some bugs when ITS mitigation is active. Juergen Gross (3): x86/execmem: don't use PAGE_KERNEL protection for code pages x86/mm/pat: don't collapse pages without PSE set x86/alternative: make kernel ITS thunks read-only arch/x86/kernel/alternative.c | 16 ++++++++++++++++ arch/x86/mm/init.c | 2 +- arch/x86/mm/pat/set_memory.c | 3 +++ 3 files changed, 20 insertions(+), 1 deletion(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages 2025-05-28 12:35 [PATCH 0/3] x86: Fix some bugs related to ITS mitigation Juergen Gross @ 2025-05-28 12:35 ` Juergen Gross 2025-05-28 17:27 ` Mike Rapoport 2025-05-28 12:35 ` [PATCH 2/3] x86/mm/pat: don't collapse pages without PSE set Juergen Gross 2025-05-28 12:35 ` [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only Juergen Gross 2 siblings, 1 reply; 18+ messages in thread From: Juergen Gross @ 2025-05-28 12:35 UTC (permalink / raw) To: linux-kernel, x86 Cc: xin, Juergen Gross, Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, stable In case X86_FEATURE_PSE isn't available (e.g. when running as a Xen PV guest), execmem_arch_setup() will fall back to use PAGE_KERNEL protection for the EXECMEM_MODULE_TEXT range. This will result in attempts to execute code with the NX bit set in case of ITS mitigation being applied. Avoid this problem by using PAGE_KERNEL_EXEC protection instead, which will not set the NX bit. Cc: <stable@vger.kernel.org> Reported-by: Xin Li <xin@zytor.com> Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") Signed-off-by: Juergen Gross <jgross@suse.com> --- arch/x86/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 7456df985d96..f5012ae31d8b 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -1089,7 +1089,7 @@ struct execmem_info __init *execmem_arch_setup(void) pgprot = PAGE_KERNEL_ROX; flags = EXECMEM_KASAN_SHADOW | EXECMEM_ROX_CACHE; } else { - pgprot = PAGE_KERNEL; + pgprot = PAGE_KERNEL_EXEC; flags = EXECMEM_KASAN_SHADOW; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages 2025-05-28 12:35 ` [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages Juergen Gross @ 2025-05-28 17:27 ` Mike Rapoport 2025-05-28 18:22 ` Jürgen Groß 2025-05-30 7:44 ` Peter Zijlstra 0 siblings, 2 replies; 18+ messages in thread From: Mike Rapoport @ 2025-05-28 17:27 UTC (permalink / raw) To: Juergen Gross Cc: linux-kernel, x86, xin, Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, stable On Wed, May 28, 2025 at 02:35:55PM +0200, Juergen Gross wrote: > In case X86_FEATURE_PSE isn't available (e.g. when running as a Xen > PV guest), execmem_arch_setup() will fall back to use PAGE_KERNEL > protection for the EXECMEM_MODULE_TEXT range. > > This will result in attempts to execute code with the NX bit set in > case of ITS mitigation being applied. > > Avoid this problem by using PAGE_KERNEL_EXEC protection instead, > which will not set the NX bit. > > Cc: <stable@vger.kernel.org> > Reported-by: Xin Li <xin@zytor.com> > Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") > Signed-off-by: Juergen Gross <jgross@suse.com> > --- > arch/x86/mm/init.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c > index 7456df985d96..f5012ae31d8b 100644 > --- a/arch/x86/mm/init.c > +++ b/arch/x86/mm/init.c > @@ -1089,7 +1089,7 @@ struct execmem_info __init *execmem_arch_setup(void) > pgprot = PAGE_KERNEL_ROX; > flags = EXECMEM_KASAN_SHADOW | EXECMEM_ROX_CACHE; > } else { > - pgprot = PAGE_KERNEL; > + pgprot = PAGE_KERNEL_EXEC; Please don't. Everything except ITS can work with PAGE_KENREL so the fix should be on ITS side. > flags = EXECMEM_KASAN_SHADOW; > } > > -- > 2.43.0 > -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages 2025-05-28 17:27 ` Mike Rapoport @ 2025-05-28 18:22 ` Jürgen Groß 2025-05-30 7:44 ` Peter Zijlstra 1 sibling, 0 replies; 18+ messages in thread From: Jürgen Groß @ 2025-05-28 18:22 UTC (permalink / raw) To: Mike Rapoport Cc: linux-kernel, x86, xin, Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, stable [-- Attachment #1.1.1: Type: text/plain, Size: 1493 bytes --] On 28.05.25 19:27, Mike Rapoport wrote: > On Wed, May 28, 2025 at 02:35:55PM +0200, Juergen Gross wrote: >> In case X86_FEATURE_PSE isn't available (e.g. when running as a Xen >> PV guest), execmem_arch_setup() will fall back to use PAGE_KERNEL >> protection for the EXECMEM_MODULE_TEXT range. >> >> This will result in attempts to execute code with the NX bit set in >> case of ITS mitigation being applied. >> >> Avoid this problem by using PAGE_KERNEL_EXEC protection instead, >> which will not set the NX bit. >> >> Cc: <stable@vger.kernel.org> >> Reported-by: Xin Li <xin@zytor.com> >> Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") >> Signed-off-by: Juergen Gross <jgross@suse.com> >> --- >> arch/x86/mm/init.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c >> index 7456df985d96..f5012ae31d8b 100644 >> --- a/arch/x86/mm/init.c >> +++ b/arch/x86/mm/init.c >> @@ -1089,7 +1089,7 @@ struct execmem_info __init *execmem_arch_setup(void) >> pgprot = PAGE_KERNEL_ROX; >> flags = EXECMEM_KASAN_SHADOW | EXECMEM_ROX_CACHE; >> } else { >> - pgprot = PAGE_KERNEL; >> + pgprot = PAGE_KERNEL_EXEC; > > Please don't. Everything except ITS can work with PAGE_KENREL so the fix > should be on ITS side. Hmm, maybe adding another element to execmem_info[] with the new type EXECMEM_KERNEL_TEXT, specifying PAGE_KERNEL_EXEC if !PSE? Juergen [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 3743 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 495 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages 2025-05-28 17:27 ` Mike Rapoport 2025-05-28 18:22 ` Jürgen Groß @ 2025-05-30 7:44 ` Peter Zijlstra 1 sibling, 0 replies; 18+ messages in thread From: Peter Zijlstra @ 2025-05-30 7:44 UTC (permalink / raw) To: Mike Rapoport Cc: Juergen Gross, linux-kernel, x86, xin, Dave Hansen, Andy Lutomirski, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, stable On Wed, May 28, 2025 at 08:27:19PM +0300, Mike Rapoport wrote: > On Wed, May 28, 2025 at 02:35:55PM +0200, Juergen Gross wrote: > > In case X86_FEATURE_PSE isn't available (e.g. when running as a Xen > > PV guest), execmem_arch_setup() will fall back to use PAGE_KERNEL > > protection for the EXECMEM_MODULE_TEXT range. > > > > This will result in attempts to execute code with the NX bit set in > > case of ITS mitigation being applied. > > > > Avoid this problem by using PAGE_KERNEL_EXEC protection instead, > > which will not set the NX bit. > > > > Cc: <stable@vger.kernel.org> > > Reported-by: Xin Li <xin@zytor.com> > > Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") > > Signed-off-by: Juergen Gross <jgross@suse.com> > > --- > > arch/x86/mm/init.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c > > index 7456df985d96..f5012ae31d8b 100644 > > --- a/arch/x86/mm/init.c > > +++ b/arch/x86/mm/init.c > > @@ -1089,7 +1089,7 @@ struct execmem_info __init *execmem_arch_setup(void) > > pgprot = PAGE_KERNEL_ROX; > > flags = EXECMEM_KASAN_SHADOW | EXECMEM_ROX_CACHE; > > } else { > > - pgprot = PAGE_KERNEL; > > + pgprot = PAGE_KERNEL_EXEC; > > Please don't. Everything except ITS can work with PAGE_KENREL so the fix > should be on ITS side. Well, this is early vs post make_ro again. Does something like so work for you? --- diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 7456df985d96..f5012ae31d8b 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -1089,7 +1089,7 @@ struct execmem_info __init *execmem_arch_setup(void) pgprot = PAGE_KERNEL_ROX; flags = EXECMEM_KASAN_SHADOW | EXECMEM_ROX_CACHE; } else { - pgprot = PAGE_KERNEL; + pgprot = PAGE_KERNEL_EXEC; flags = EXECMEM_KASAN_SHADOW; } diff --git a/mm/execmem.c b/mm/execmem.c index 6f7a2653b280..dbe2eedea0e6 100644 --- a/mm/execmem.c +++ b/mm/execmem.c @@ -258,6 +258,7 @@ static bool execmem_cache_rox = false; void execmem_cache_make_ro(void) { + struct execmem_range *module_text = &execmem_info->ranges[EXECMEM_MODULE_TEXT]; struct maple_tree *free_areas = &execmem_cache.free_areas; struct maple_tree *busy_areas = &execmem_cache.busy_areas; MA_STATE(mas_free, free_areas, 0, ULONG_MAX); @@ -269,6 +270,9 @@ void execmem_cache_make_ro(void) mutex_lock(mutex); + if (!(module_text->flags & EXECMEM_ROX_CACHE)) + module_text->pgprot = PAGE_KERNEL; + mas_for_each(&mas_free, area, ULONG_MAX) { unsigned long pages = mas_range_len(&mas_free) >> PAGE_SHIFT; set_memory_ro(mas_free.index, pages); ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 2/3] x86/mm/pat: don't collapse pages without PSE set 2025-05-28 12:35 [PATCH 0/3] x86: Fix some bugs related to ITS mitigation Juergen Gross 2025-05-28 12:35 ` [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages Juergen Gross @ 2025-05-28 12:35 ` Juergen Gross 2025-06-11 9:30 ` [tip: x86/urgent] " tip-bot2 for Juergen Gross 2025-05-28 12:35 ` [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only Juergen Gross 2 siblings, 1 reply; 18+ messages in thread From: Juergen Gross @ 2025-05-28 12:35 UTC (permalink / raw) To: linux-kernel, x86 Cc: xin, Juergen Gross, Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, stable Collapsing pages to a leaf PMD or PUD should be done only if X86_FEATURE_PSE is available, which is not the case when running e.g. as a Xen PV guest. Cc: <stable@vger.kernel.org> Fixes: 41d88484c71c ("x86/mm/pat: restore large ROX pages after fragmentation") Signed-off-by: Juergen Gross <jgross@suse.com> --- arch/x86/mm/pat/set_memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 30ab4aced761..e6a6ac8cdc1d 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -1257,6 +1257,9 @@ static int collapse_pmd_page(pmd_t *pmd, unsigned long addr, pgprot_t pgprot; int i = 0; + if (!cpu_feature_enabled(X86_FEATURE_PSE)) + return 0; + addr &= PMD_MASK; pte = pte_offset_kernel(pmd, addr); first = *pte; -- 2.43.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [tip: x86/urgent] x86/mm/pat: don't collapse pages without PSE set 2025-05-28 12:35 ` [PATCH 2/3] x86/mm/pat: don't collapse pages without PSE set Juergen Gross @ 2025-06-11 9:30 ` tip-bot2 for Juergen Gross 0 siblings, 0 replies; 18+ messages in thread From: tip-bot2 for Juergen Gross @ 2025-06-11 9:30 UTC (permalink / raw) To: linux-tip-commits Cc: Juergen Gross, Mike Rapoport (Microsoft), Peter Zijlstra (Intel), stable, x86, linux-kernel The following commit has been merged into the x86/urgent branch of tip: Commit-ID: 1dbf30fdb5e57fb2c39f17f35f2b544d5de34397 Gitweb: https://git.kernel.org/tip/1dbf30fdb5e57fb2c39f17f35f2b544d5de34397 Author: Juergen Gross <jgross@suse.com> AuthorDate: Tue, 03 Jun 2025 14:14:41 +03:00 Committer: Peter Zijlstra <peterz@infradead.org> CommitterDate: Wed, 11 Jun 2025 11:20:51 +02:00 x86/mm/pat: don't collapse pages without PSE set Collapsing pages to a leaf PMD or PUD should be done only if X86_FEATURE_PSE is available, which is not the case when running e.g. as a Xen PV guest. Fixes: 41d88484c71c ("x86/mm/pat: restore large ROX pages after fragmentation") Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250528123557.12847-3-jgross@suse.com --- arch/x86/mm/pat/set_memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 46edc11..8834c76 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -1257,6 +1257,9 @@ static int collapse_pmd_page(pmd_t *pmd, unsigned long addr, pgprot_t pgprot; int i = 0; + if (!cpu_feature_enabled(X86_FEATURE_PSE)) + return 0; + addr &= PMD_MASK; pte = pte_offset_kernel(pmd, addr); first = *pte; ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 12:35 [PATCH 0/3] x86: Fix some bugs related to ITS mitigation Juergen Gross 2025-05-28 12:35 ` [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages Juergen Gross 2025-05-28 12:35 ` [PATCH 2/3] x86/mm/pat: don't collapse pages without PSE set Juergen Gross @ 2025-05-28 12:35 ` Juergen Gross 2025-05-28 13:10 ` Peter Zijlstra 2025-05-29 4:09 ` kernel test robot 2 siblings, 2 replies; 18+ messages in thread From: Juergen Gross @ 2025-05-28 12:35 UTC (permalink / raw) To: linux-kernel, x86 Cc: xin, Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable When allocating memory pages for kernel ITS thunks, make them read-only after having written the last thunk. This will be needed when X86_FEATURE_PSE isn't available, as the thunk memory will have PAGE_KERNEL_EXEC protection, which is including the write permission. Cc: <stable@vger.kernel.org> Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") Signed-off-by: Juergen Gross <jgross@suse.com> --- arch/x86/kernel/alternative.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ecfe7b497cad..bd974a0ac88a 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -217,6 +217,15 @@ static void *its_alloc(void) return no_free_ptr(page); } +static void its_set_kernel_ro(void *addr) +{ +#ifdef CONFIG_MODULES + if (its_mod) + return; +#endif + execmem_restore_rox(addr, PAGE_SIZE); +} + static void *its_allocate_thunk(int reg) { int size = 3 + (reg / 8); @@ -234,6 +243,8 @@ static void *its_allocate_thunk(int reg) #endif if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) { + if (its_page) + its_set_kernel_ro(its_page); its_page = its_alloc(); if (!its_page) { pr_err("ITS page allocation failed\n"); @@ -2338,6 +2349,11 @@ void __init alternative_instructions(void) apply_retpolines(__retpoline_sites, __retpoline_sites_end); apply_returns(__return_sites, __return_sites_end); + /* Make potential last thunk page read-only. */ + if (its_page) + its_set_kernel_ro(its_page); + its_page = NULL; + /* * Adjust all CALL instructions to point to func()-10, including * those in .altinstr_replacement. -- 2.43.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 12:35 ` [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only Juergen Gross @ 2025-05-28 13:10 ` Peter Zijlstra 2025-05-28 13:19 ` Jürgen Groß 2025-05-29 4:09 ` kernel test robot 1 sibling, 1 reply; 18+ messages in thread From: Peter Zijlstra @ 2025-05-28 13:10 UTC (permalink / raw) To: Juergen Gross Cc: linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable On Wed, May 28, 2025 at 02:35:57PM +0200, Juergen Gross wrote: > When allocating memory pages for kernel ITS thunks, make them read-only > after having written the last thunk. > > This will be needed when X86_FEATURE_PSE isn't available, as the thunk > memory will have PAGE_KERNEL_EXEC protection, which is including the > write permission. > > Cc: <stable@vger.kernel.org> > Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") > Signed-off-by: Juergen Gross <jgross@suse.com> > --- > arch/x86/kernel/alternative.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > index ecfe7b497cad..bd974a0ac88a 100644 > --- a/arch/x86/kernel/alternative.c > +++ b/arch/x86/kernel/alternative.c > @@ -217,6 +217,15 @@ static void *its_alloc(void) > return no_free_ptr(page); > } > > +static void its_set_kernel_ro(void *addr) > +{ > +#ifdef CONFIG_MODULES > + if (its_mod) > + return; > +#endif > + execmem_restore_rox(addr, PAGE_SIZE); > +} > + > static void *its_allocate_thunk(int reg) > { > int size = 3 + (reg / 8); > @@ -234,6 +243,8 @@ static void *its_allocate_thunk(int reg) > #endif > > if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) { > + if (its_page) > + its_set_kernel_ro(its_page); > its_page = its_alloc(); > if (!its_page) { > pr_err("ITS page allocation failed\n"); > @@ -2338,6 +2349,11 @@ void __init alternative_instructions(void) > apply_retpolines(__retpoline_sites, __retpoline_sites_end); > apply_returns(__return_sites, __return_sites_end); > > + /* Make potential last thunk page read-only. */ > + if (its_page) > + its_set_kernel_ro(its_page); > + its_page = NULL; > + > /* > * Adjust all CALL instructions to point to func()-10, including > * those in .altinstr_replacement. No, this is all sorts of wrong. Execmem API should ensure this. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 13:10 ` Peter Zijlstra @ 2025-05-28 13:19 ` Jürgen Groß 2025-05-28 13:22 ` Peter Zijlstra 0 siblings, 1 reply; 18+ messages in thread From: Jürgen Groß @ 2025-05-28 13:19 UTC (permalink / raw) To: Peter Zijlstra Cc: linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable [-- Attachment #1.1.1: Type: text/plain, Size: 2237 bytes --] On 28.05.25 15:10, Peter Zijlstra wrote: > On Wed, May 28, 2025 at 02:35:57PM +0200, Juergen Gross wrote: >> When allocating memory pages for kernel ITS thunks, make them read-only >> after having written the last thunk. >> >> This will be needed when X86_FEATURE_PSE isn't available, as the thunk >> memory will have PAGE_KERNEL_EXEC protection, which is including the >> write permission. >> >> Cc: <stable@vger.kernel.org> >> Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") >> Signed-off-by: Juergen Gross <jgross@suse.com> >> --- >> arch/x86/kernel/alternative.c | 16 ++++++++++++++++ >> 1 file changed, 16 insertions(+) >> >> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c >> index ecfe7b497cad..bd974a0ac88a 100644 >> --- a/arch/x86/kernel/alternative.c >> +++ b/arch/x86/kernel/alternative.c >> @@ -217,6 +217,15 @@ static void *its_alloc(void) >> return no_free_ptr(page); >> } >> >> +static void its_set_kernel_ro(void *addr) >> +{ >> +#ifdef CONFIG_MODULES >> + if (its_mod) >> + return; >> +#endif >> + execmem_restore_rox(addr, PAGE_SIZE); >> +} >> + >> static void *its_allocate_thunk(int reg) >> { >> int size = 3 + (reg / 8); >> @@ -234,6 +243,8 @@ static void *its_allocate_thunk(int reg) >> #endif >> >> if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) { >> + if (its_page) >> + its_set_kernel_ro(its_page); >> its_page = its_alloc(); >> if (!its_page) { >> pr_err("ITS page allocation failed\n"); >> @@ -2338,6 +2349,11 @@ void __init alternative_instructions(void) >> apply_retpolines(__retpoline_sites, __retpoline_sites_end); >> apply_returns(__return_sites, __return_sites_end); >> >> + /* Make potential last thunk page read-only. */ >> + if (its_page) >> + its_set_kernel_ro(its_page); >> + its_page = NULL; >> + >> /* >> * Adjust all CALL instructions to point to func()-10, including >> * those in .altinstr_replacement. > > No, this is all sorts of wrong. Execmem API should ensure this. You are aware that this patch is basically mirroring the work which is already done for modules in alternative.c? Juergen [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 3743 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 495 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 13:19 ` Jürgen Groß @ 2025-05-28 13:22 ` Peter Zijlstra 2025-05-28 13:30 ` Jürgen Groß 0 siblings, 1 reply; 18+ messages in thread From: Peter Zijlstra @ 2025-05-28 13:22 UTC (permalink / raw) To: Jürgen Groß Cc: linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable On Wed, May 28, 2025 at 03:19:24PM +0200, Jürgen Groß wrote: > On 28.05.25 15:10, Peter Zijlstra wrote: > > On Wed, May 28, 2025 at 02:35:57PM +0200, Juergen Gross wrote: > > > When allocating memory pages for kernel ITS thunks, make them read-only > > > after having written the last thunk. > > > > > > This will be needed when X86_FEATURE_PSE isn't available, as the thunk > > > memory will have PAGE_KERNEL_EXEC protection, which is including the > > > write permission. > > > > > > Cc: <stable@vger.kernel.org> > > > Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") > > > Signed-off-by: Juergen Gross <jgross@suse.com> > > > --- > > > arch/x86/kernel/alternative.c | 16 ++++++++++++++++ > > > 1 file changed, 16 insertions(+) > > > > > > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > > > index ecfe7b497cad..bd974a0ac88a 100644 > > > --- a/arch/x86/kernel/alternative.c > > > +++ b/arch/x86/kernel/alternative.c > > > @@ -217,6 +217,15 @@ static void *its_alloc(void) > > > return no_free_ptr(page); > > > } > > > +static void its_set_kernel_ro(void *addr) > > > +{ > > > +#ifdef CONFIG_MODULES > > > + if (its_mod) > > > + return; > > > +#endif > > > + execmem_restore_rox(addr, PAGE_SIZE); > > > +} > > > + > > > static void *its_allocate_thunk(int reg) > > > { > > > int size = 3 + (reg / 8); > > > @@ -234,6 +243,8 @@ static void *its_allocate_thunk(int reg) > > > #endif > > > if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) { > > > + if (its_page) > > > + its_set_kernel_ro(its_page); > > > its_page = its_alloc(); > > > if (!its_page) { > > > pr_err("ITS page allocation failed\n"); > > > @@ -2338,6 +2349,11 @@ void __init alternative_instructions(void) > > > apply_retpolines(__retpoline_sites, __retpoline_sites_end); > > > apply_returns(__return_sites, __return_sites_end); > > > + /* Make potential last thunk page read-only. */ > > > + if (its_page) > > > + its_set_kernel_ro(its_page); > > > + its_page = NULL; > > > + > > > /* > > > * Adjust all CALL instructions to point to func()-10, including > > > * those in .altinstr_replacement. > > > > No, this is all sorts of wrong. Execmem API should ensure this. > > You are aware that this patch is basically mirroring the work which is > already done for modules in alternative.c? I am having trouble parsing that -- where does alternative.c do this to modules? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 13:22 ` Peter Zijlstra @ 2025-05-28 13:30 ` Jürgen Groß 2025-05-28 15:58 ` Peter Zijlstra 0 siblings, 1 reply; 18+ messages in thread From: Jürgen Groß @ 2025-05-28 13:30 UTC (permalink / raw) To: Peter Zijlstra Cc: linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable [-- Attachment #1.1.1: Type: text/plain, Size: 2586 bytes --] On 28.05.25 15:22, Peter Zijlstra wrote: > On Wed, May 28, 2025 at 03:19:24PM +0200, Jürgen Groß wrote: >> On 28.05.25 15:10, Peter Zijlstra wrote: >>> On Wed, May 28, 2025 at 02:35:57PM +0200, Juergen Gross wrote: >>>> When allocating memory pages for kernel ITS thunks, make them read-only >>>> after having written the last thunk. >>>> >>>> This will be needed when X86_FEATURE_PSE isn't available, as the thunk >>>> memory will have PAGE_KERNEL_EXEC protection, which is including the >>>> write permission. >>>> >>>> Cc: <stable@vger.kernel.org> >>>> Fixes: 5185e7f9f3bd ("x86/module: enable ROX caches for module text on 64 bit") >>>> Signed-off-by: Juergen Gross <jgross@suse.com> >>>> --- >>>> arch/x86/kernel/alternative.c | 16 ++++++++++++++++ >>>> 1 file changed, 16 insertions(+) >>>> >>>> diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c >>>> index ecfe7b497cad..bd974a0ac88a 100644 >>>> --- a/arch/x86/kernel/alternative.c >>>> +++ b/arch/x86/kernel/alternative.c >>>> @@ -217,6 +217,15 @@ static void *its_alloc(void) >>>> return no_free_ptr(page); >>>> } >>>> +static void its_set_kernel_ro(void *addr) >>>> +{ >>>> +#ifdef CONFIG_MODULES >>>> + if (its_mod) >>>> + return; >>>> +#endif >>>> + execmem_restore_rox(addr, PAGE_SIZE); >>>> +} >>>> + >>>> static void *its_allocate_thunk(int reg) >>>> { >>>> int size = 3 + (reg / 8); >>>> @@ -234,6 +243,8 @@ static void *its_allocate_thunk(int reg) >>>> #endif >>>> if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) { >>>> + if (its_page) >>>> + its_set_kernel_ro(its_page); >>>> its_page = its_alloc(); >>>> if (!its_page) { >>>> pr_err("ITS page allocation failed\n"); >>>> @@ -2338,6 +2349,11 @@ void __init alternative_instructions(void) >>>> apply_retpolines(__retpoline_sites, __retpoline_sites_end); >>>> apply_returns(__return_sites, __return_sites_end); >>>> + /* Make potential last thunk page read-only. */ >>>> + if (its_page) >>>> + its_set_kernel_ro(its_page); >>>> + its_page = NULL; >>>> + >>>> /* >>>> * Adjust all CALL instructions to point to func()-10, including >>>> * those in .altinstr_replacement. >>> >>> No, this is all sorts of wrong. Execmem API should ensure this. >> >> You are aware that this patch is basically mirroring the work which is >> already done for modules in alternative.c? > > I am having trouble parsing that -- where does alternative.c do this to > modules? Have a look at its_fini_mod(). Juergen [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 3743 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 495 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 13:30 ` Jürgen Groß @ 2025-05-28 15:58 ` Peter Zijlstra 2025-05-28 16:17 ` Peter Zijlstra ` (3 more replies) 0 siblings, 4 replies; 18+ messages in thread From: Peter Zijlstra @ 2025-05-28 15:58 UTC (permalink / raw) To: Jürgen Groß Cc: linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable, rppt On Wed, May 28, 2025 at 03:30:33PM +0200, Jürgen Groß wrote: > Have a look at its_fini_mod(). Oh, that's what you mean. But this still isn't very nice, you now have restore_rox() without make_temp_rw(), which was the intended usage pattern. Bah, I hate how execmem works different for !PSE, Mike, you see a sane way to fix this? Anyway, if we have to do something like this, then I would prefer it shaped something like so: --- diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ecfe7b497cad..33d4d139cb50 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -111,9 +111,8 @@ static bool cfi_paranoid __ro_after_init; #ifdef CONFIG_MITIGATION_ITS -#ifdef CONFIG_MODULES static struct module *its_mod; -#endif +static struct its_array its_pages; static void *its_page; static unsigned int its_offset; @@ -151,68 +150,78 @@ static void *its_init_thunk(void *thunk, int reg) return thunk + offset; } -#ifdef CONFIG_MODULES void its_init_mod(struct module *mod) { if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) return; - mutex_lock(&text_mutex); - its_mod = mod; - its_page = NULL; + if (mod) { + mutex_lock(&text_mutex); + its_mod = mod; + its_page = NULL; + } } void its_fini_mod(struct module *mod) { + struct its_array *pages = &its_pages; + if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) return; WARN_ON_ONCE(its_mod != mod); - its_mod = NULL; - its_page = NULL; - mutex_unlock(&text_mutex); + if (mod) { + pages = &mod->arch.its_pages; + its_mod = NULL; + its_page = NULL; + mutex_unlock(&text_mutex); + } - for (int i = 0; i < mod->its_num_pages; i++) { - void *page = mod->its_page_array[i]; + for (int i = 0; i < pages->num; i++) { + void *page = pages->pages[i]; execmem_restore_rox(page, PAGE_SIZE); } + + if (!mod) + kfree(pages->pages); } void its_free_mod(struct module *mod) { + struct its_array *pages = &its_pages; + if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) return; - for (int i = 0; i < mod->its_num_pages; i++) { - void *page = mod->its_page_array[i]; + if (mod) + pages = &mod->arch.its_pages; + + for (int i = 0; i < pages->num; i++) { + void *page = pages->pages[i]; execmem_free(page); } - kfree(mod->its_page_array); + kfree(pages->pages); } -#endif /* CONFIG_MODULES */ static void *its_alloc(void) { - void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); + struct its_array *pages = &its_pages; + void *tmp; + void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); if (!page) return NULL; -#ifdef CONFIG_MODULES - if (its_mod) { - void *tmp = krealloc(its_mod->its_page_array, - (its_mod->its_num_pages+1) * sizeof(void *), - GFP_KERNEL); - if (!tmp) - return NULL; + tmp = krealloc(pages->pages, (pages->num + 1) * sizeof(void *), GFP_KERNEL); + if (!tmp) + return NULL; - its_mod->its_page_array = tmp; - its_mod->its_page_array[its_mod->its_num_pages++] = page; + pages->pages = tmp; + pages->pages[pages->num++] = page; + if (its_mod) execmem_make_temp_rw(page, PAGE_SIZE); - } -#endif /* CONFIG_MODULES */ return no_free_ptr(page); } @@ -2338,6 +2347,8 @@ void __init alternative_instructions(void) apply_retpolines(__retpoline_sites, __retpoline_sites_end); apply_returns(__return_sites, __return_sites_end); + its_fini_mod(NULL); + /* * Adjust all CALL instructions to point to func()-10, including * those in .altinstr_replacement. ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 15:58 ` Peter Zijlstra @ 2025-05-28 16:17 ` Peter Zijlstra 2025-05-28 17:24 ` Mike Rapoport ` (2 subsequent siblings) 3 siblings, 0 replies; 18+ messages in thread From: Peter Zijlstra @ 2025-05-28 16:17 UTC (permalink / raw) To: Jürgen Groß Cc: linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable, rppt On Wed, May 28, 2025 at 05:58:21PM +0200, Peter Zijlstra wrote: > On Wed, May 28, 2025 at 03:30:33PM +0200, Jürgen Groß wrote: > > > Have a look at its_fini_mod(). > > Oh, that's what you mean. But this still isn't very nice, you now have > restore_rox() without make_temp_rw(), which was the intended usage > pattern. > > Bah, I hate how execmem works different for !PSE, Mike, you see a sane > way to fix this? > > Anyway, if we have to do something like this, then I would prefer it > shaped something like so: > Missing file: diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h index e988bac0a4a1..3c2de4ce3b10 100644 --- a/arch/x86/include/asm/module.h +++ b/arch/x86/include/asm/module.h @@ -5,12 +5,20 @@ #include <asm-generic/module.h> #include <asm/orc_types.h> +struct its_array { +#ifdef CONFIG_MITIGATION_ITS + void **pages; + int num; +#endif +}; + struct mod_arch_specific { #ifdef CONFIG_UNWINDER_ORC unsigned int num_orcs; int *orc_unwind_ip; struct orc_entry *orc_unwind; #endif + struct its_array its_pages; }; #endif /* _ASM_X86_MODULE_H */ > --- > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > index ecfe7b497cad..33d4d139cb50 100644 > --- a/arch/x86/kernel/alternative.c > +++ b/arch/x86/kernel/alternative.c > @@ -111,9 +111,8 @@ static bool cfi_paranoid __ro_after_init; > > #ifdef CONFIG_MITIGATION_ITS > > -#ifdef CONFIG_MODULES > static struct module *its_mod; > -#endif > +static struct its_array its_pages; > static void *its_page; > static unsigned int its_offset; > > @@ -151,68 +150,78 @@ static void *its_init_thunk(void *thunk, int reg) > return thunk + offset; > } > > -#ifdef CONFIG_MODULES > void its_init_mod(struct module *mod) > { > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > - mutex_lock(&text_mutex); > - its_mod = mod; > - its_page = NULL; > + if (mod) { > + mutex_lock(&text_mutex); > + its_mod = mod; > + its_page = NULL; > + } > } > > void its_fini_mod(struct module *mod) > { > + struct its_array *pages = &its_pages; > + > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > WARN_ON_ONCE(its_mod != mod); > > - its_mod = NULL; > - its_page = NULL; > - mutex_unlock(&text_mutex); > + if (mod) { > + pages = &mod->arch.its_pages; > + its_mod = NULL; > + its_page = NULL; > + mutex_unlock(&text_mutex); > + } > > - for (int i = 0; i < mod->its_num_pages; i++) { > - void *page = mod->its_page_array[i]; > + for (int i = 0; i < pages->num; i++) { > + void *page = pages->pages[i]; > execmem_restore_rox(page, PAGE_SIZE); > } > + > + if (!mod) > + kfree(pages->pages); > } > > void its_free_mod(struct module *mod) > { > + struct its_array *pages = &its_pages; > + > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > - for (int i = 0; i < mod->its_num_pages; i++) { > - void *page = mod->its_page_array[i]; > + if (mod) > + pages = &mod->arch.its_pages; > + > + for (int i = 0; i < pages->num; i++) { > + void *page = pages->pages[i]; > execmem_free(page); > } > - kfree(mod->its_page_array); > + kfree(pages->pages); > } > -#endif /* CONFIG_MODULES */ > > static void *its_alloc(void) > { > - void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); > + struct its_array *pages = &its_pages; > + void *tmp; > > + void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); > if (!page) > return NULL; > > -#ifdef CONFIG_MODULES > - if (its_mod) { > - void *tmp = krealloc(its_mod->its_page_array, > - (its_mod->its_num_pages+1) * sizeof(void *), > - GFP_KERNEL); > - if (!tmp) > - return NULL; > + tmp = krealloc(pages->pages, (pages->num + 1) * sizeof(void *), GFP_KERNEL); > + if (!tmp) > + return NULL; > > - its_mod->its_page_array = tmp; > - its_mod->its_page_array[its_mod->its_num_pages++] = page; > + pages->pages = tmp; > + pages->pages[pages->num++] = page; > > + if (its_mod) > execmem_make_temp_rw(page, PAGE_SIZE); > - } > -#endif /* CONFIG_MODULES */ > > return no_free_ptr(page); > } > @@ -2338,6 +2347,8 @@ void __init alternative_instructions(void) > apply_retpolines(__retpoline_sites, __retpoline_sites_end); > apply_returns(__return_sites, __return_sites_end); > > + its_fini_mod(NULL); > + > /* > * Adjust all CALL instructions to point to func()-10, including > * those in .altinstr_replacement. ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 15:58 ` Peter Zijlstra 2025-05-28 16:17 ` Peter Zijlstra @ 2025-05-28 17:24 ` Mike Rapoport 2025-05-28 17:31 ` Mike Rapoport 2025-06-03 11:17 ` Mike Rapoport 3 siblings, 0 replies; 18+ messages in thread From: Mike Rapoport @ 2025-05-28 17:24 UTC (permalink / raw) To: Peter Zijlstra Cc: Jürgen Groß, linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable On Wed, May 28, 2025 at 05:58:21PM +0200, Peter Zijlstra wrote: > On Wed, May 28, 2025 at 03:30:33PM +0200, Jürgen Groß wrote: > > > Have a look at its_fini_mod(). > > Oh, that's what you mean. But this still isn't very nice, you now have > restore_rox() without make_temp_rw(), which was the intended usage > pattern. > > Bah, I hate how execmem works different for !PSE, Mike, you see a sane > way to fix this? Not really :( But just resetting permissions in the end like you did makes perfect sense to me. It's like STRICT_MODULE_RWX, somebody has to set the pages to ROX at some point and running execmem_restore_rox() on something that was already ROX won't cost much, set_memory will bail out early. > Anyway, if we have to do something like this, then I would prefer it > shaped something like so: > > --- > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > index ecfe7b497cad..33d4d139cb50 100644 > --- a/arch/x86/kernel/alternative.c > +++ b/arch/x86/kernel/alternative.c > @@ -111,9 +111,8 @@ static bool cfi_paranoid __ro_after_init; > > #ifdef CONFIG_MITIGATION_ITS > > -#ifdef CONFIG_MODULES > static struct module *its_mod; > -#endif > +static struct its_array its_pages; > static void *its_page; > static unsigned int its_offset; > > @@ -151,68 +150,78 @@ static void *its_init_thunk(void *thunk, int reg) > return thunk + offset; > } > > -#ifdef CONFIG_MODULES > void its_init_mod(struct module *mod) > { > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > - mutex_lock(&text_mutex); > - its_mod = mod; > - its_page = NULL; > + if (mod) { > + mutex_lock(&text_mutex); > + its_mod = mod; > + its_page = NULL; > + } > } > > void its_fini_mod(struct module *mod) > { > + struct its_array *pages = &its_pages; > + > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > WARN_ON_ONCE(its_mod != mod); > > - its_mod = NULL; > - its_page = NULL; > - mutex_unlock(&text_mutex); > + if (mod) { > + pages = &mod->arch.its_pages; > + its_mod = NULL; > + its_page = NULL; > + mutex_unlock(&text_mutex); > + } > > - for (int i = 0; i < mod->its_num_pages; i++) { > - void *page = mod->its_page_array[i]; > + for (int i = 0; i < pages->num; i++) { > + void *page = pages->pages[i]; > execmem_restore_rox(page, PAGE_SIZE); > } > + > + if (!mod) > + kfree(pages->pages); > } > > void its_free_mod(struct module *mod) > { > + struct its_array *pages = &its_pages; > + > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > - for (int i = 0; i < mod->its_num_pages; i++) { > - void *page = mod->its_page_array[i]; > + if (mod) > + pages = &mod->arch.its_pages; > + > + for (int i = 0; i < pages->num; i++) { > + void *page = pages->pages[i]; > execmem_free(page); > } > - kfree(mod->its_page_array); > + kfree(pages->pages); > } > -#endif /* CONFIG_MODULES */ > > static void *its_alloc(void) > { > - void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); > + struct its_array *pages = &its_pages; > + void *tmp; > > + void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); > if (!page) > return NULL; > > -#ifdef CONFIG_MODULES > - if (its_mod) { > - void *tmp = krealloc(its_mod->its_page_array, > - (its_mod->its_num_pages+1) * sizeof(void *), > - GFP_KERNEL); > - if (!tmp) > - return NULL; > + tmp = krealloc(pages->pages, (pages->num + 1) * sizeof(void *), GFP_KERNEL); > + if (!tmp) > + return NULL; > > - its_mod->its_page_array = tmp; > - its_mod->its_page_array[its_mod->its_num_pages++] = page; > + pages->pages = tmp; > + pages->pages[pages->num++] = page; > > + if (its_mod) > execmem_make_temp_rw(page, PAGE_SIZE); > - } > -#endif /* CONFIG_MODULES */ > > return no_free_ptr(page); > } > @@ -2338,6 +2347,8 @@ void __init alternative_instructions(void) > apply_retpolines(__retpoline_sites, __retpoline_sites_end); > apply_returns(__return_sites, __return_sites_end); > > + its_fini_mod(NULL); > + > /* > * Adjust all CALL instructions to point to func()-10, including > * those in .altinstr_replacement. -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 15:58 ` Peter Zijlstra 2025-05-28 16:17 ` Peter Zijlstra 2025-05-28 17:24 ` Mike Rapoport @ 2025-05-28 17:31 ` Mike Rapoport 2025-06-03 11:17 ` Mike Rapoport 3 siblings, 0 replies; 18+ messages in thread From: Mike Rapoport @ 2025-05-28 17:31 UTC (permalink / raw) To: Peter Zijlstra Cc: Jürgen Groß, linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable On Wed, May 28, 2025 at 05:58:21PM +0200, Peter Zijlstra wrote: > On Wed, May 28, 2025 at 03:30:33PM +0200, Jürgen Groß wrote: > > > Have a look at its_fini_mod(). > > Oh, that's what you mean. But this still isn't very nice, you now have > restore_rox() without make_temp_rw(), which was the intended usage > pattern. > > Bah, I hate how execmem works different for !PSE, Mike, you see a sane > way to fix this? The least ugly thing I could think of is to replace the current pattern of execmem_alloc() exemem_make_temp_rw() /* update */ execmem_restore_rox() with execmem_alloc_rw() /* update */ execmem_protect() but I still haven't got to try it. -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 15:58 ` Peter Zijlstra ` (2 preceding siblings ...) 2025-05-28 17:31 ` Mike Rapoport @ 2025-06-03 11:17 ` Mike Rapoport 3 siblings, 0 replies; 18+ messages in thread From: Mike Rapoport @ 2025-06-03 11:17 UTC (permalink / raw) To: Peter Zijlstra Cc: Jürgen Groß, linux-kernel, x86, xin, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable On Wed, May 28, 2025 at 05:58:21PM +0200, Peter Zijlstra wrote: > On Wed, May 28, 2025 at 03:30:33PM +0200, Jürgen Groß wrote: > > > Have a look at its_fini_mod(). > > Oh, that's what you mean. But this still isn't very nice, you now have > restore_rox() without make_temp_rw(), which was the intended usage > pattern. > > Bah, I hate how execmem works different for !PSE, Mike, you see a sane > way to fix this? > > Anyway, if we have to do something like this, then I would prefer it > shaped something like so: I expanded this a bit and here's what I've got: https://lore.kernel.org/lkml/20250603111446.2609381-1-rppt@kernel.org/ > --- > diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c > index ecfe7b497cad..33d4d139cb50 100644 > --- a/arch/x86/kernel/alternative.c > +++ b/arch/x86/kernel/alternative.c > @@ -111,9 +111,8 @@ static bool cfi_paranoid __ro_after_init; > > #ifdef CONFIG_MITIGATION_ITS > > -#ifdef CONFIG_MODULES > static struct module *its_mod; > -#endif > +static struct its_array its_pages; > static void *its_page; > static unsigned int its_offset; > > @@ -151,68 +150,78 @@ static void *its_init_thunk(void *thunk, int reg) > return thunk + offset; > } > > -#ifdef CONFIG_MODULES > void its_init_mod(struct module *mod) > { > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > - mutex_lock(&text_mutex); > - its_mod = mod; > - its_page = NULL; > + if (mod) { > + mutex_lock(&text_mutex); > + its_mod = mod; > + its_page = NULL; > + } > } > > void its_fini_mod(struct module *mod) > { > + struct its_array *pages = &its_pages; > + > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > WARN_ON_ONCE(its_mod != mod); > > - its_mod = NULL; > - its_page = NULL; > - mutex_unlock(&text_mutex); > + if (mod) { > + pages = &mod->arch.its_pages; > + its_mod = NULL; > + its_page = NULL; > + mutex_unlock(&text_mutex); > + } > > - for (int i = 0; i < mod->its_num_pages; i++) { > - void *page = mod->its_page_array[i]; > + for (int i = 0; i < pages->num; i++) { > + void *page = pages->pages[i]; > execmem_restore_rox(page, PAGE_SIZE); > } > + > + if (!mod) > + kfree(pages->pages); > } > > void its_free_mod(struct module *mod) > { > + struct its_array *pages = &its_pages; > + > if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) > return; > > - for (int i = 0; i < mod->its_num_pages; i++) { > - void *page = mod->its_page_array[i]; > + if (mod) > + pages = &mod->arch.its_pages; > + > + for (int i = 0; i < pages->num; i++) { > + void *page = pages->pages[i]; > execmem_free(page); > } > - kfree(mod->its_page_array); > + kfree(pages->pages); > } > -#endif /* CONFIG_MODULES */ > > static void *its_alloc(void) > { > - void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); > + struct its_array *pages = &its_pages; > + void *tmp; > > + void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); > if (!page) > return NULL; > > -#ifdef CONFIG_MODULES > - if (its_mod) { > - void *tmp = krealloc(its_mod->its_page_array, > - (its_mod->its_num_pages+1) * sizeof(void *), > - GFP_KERNEL); > - if (!tmp) > - return NULL; > + tmp = krealloc(pages->pages, (pages->num + 1) * sizeof(void *), GFP_KERNEL); > + if (!tmp) > + return NULL; > > - its_mod->its_page_array = tmp; > - its_mod->its_page_array[its_mod->its_num_pages++] = page; > + pages->pages = tmp; > + pages->pages[pages->num++] = page; > > + if (its_mod) > execmem_make_temp_rw(page, PAGE_SIZE); > - } > -#endif /* CONFIG_MODULES */ > > return no_free_ptr(page); > } > @@ -2338,6 +2347,8 @@ void __init alternative_instructions(void) > apply_retpolines(__retpoline_sites, __retpoline_sites_end); > apply_returns(__return_sites, __return_sites_end); > > + its_fini_mod(NULL); > + > /* > * Adjust all CALL instructions to point to func()-10, including > * those in .altinstr_replacement. -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only 2025-05-28 12:35 ` [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only Juergen Gross 2025-05-28 13:10 ` Peter Zijlstra @ 2025-05-29 4:09 ` kernel test robot 1 sibling, 0 replies; 18+ messages in thread From: kernel test robot @ 2025-05-29 4:09 UTC (permalink / raw) To: Juergen Gross, linux-kernel, x86 Cc: llvm, oe-kbuild-all, xin, Juergen Gross, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, H. Peter Anvin, stable Hi Juergen, kernel test robot noticed the following build errors: [auto build test ERROR on tip/master] [also build test ERROR on tip/x86/core linus/master v6.15 next-20250528] [cannot apply to tip/x86/mm tip/auto-latest] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Juergen-Gross/x86-execmem-don-t-use-PAGE_KERNEL-protection-for-code-pages/20250528-204423 base: tip/master patch link: https://lore.kernel.org/r/20250528123557.12847-4-jgross%40suse.com patch subject: [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only config: x86_64-buildonly-randconfig-002-20250529 (https://download.01.org/0day-ci/archive/20250529/202505291124.eAZ7fgbG-lkp@intel.com/config) compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250529/202505291124.eAZ7fgbG-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202505291124.eAZ7fgbG-lkp@intel.com/ All errors (new ones prefixed by >>): >> arch/x86/kernel/alternative.c:2353:6: error: use of undeclared identifier 'its_page' 2353 | if (its_page) | ^ >> arch/x86/kernel/alternative.c:2354:3: error: call to undeclared function 'its_set_kernel_ro'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] 2354 | its_set_kernel_ro(its_page); | ^ arch/x86/kernel/alternative.c:2354:21: error: use of undeclared identifier 'its_page' 2354 | its_set_kernel_ro(its_page); | ^ arch/x86/kernel/alternative.c:2355:2: error: use of undeclared identifier 'its_page' 2355 | its_page = NULL; | ^ 4 errors generated. vim +/its_page +2353 arch/x86/kernel/alternative.c 2308 2309 void __init alternative_instructions(void) 2310 { 2311 u64 ibt; 2312 2313 int3_selftest(); 2314 2315 /* 2316 * The patching is not fully atomic, so try to avoid local 2317 * interruptions that might execute the to be patched code. 2318 * Other CPUs are not running. 2319 */ 2320 stop_nmi(); 2321 2322 /* 2323 * Don't stop machine check exceptions while patching. 2324 * MCEs only happen when something got corrupted and in this 2325 * case we must do something about the corruption. 2326 * Ignoring it is worse than an unlikely patching race. 2327 * Also machine checks tend to be broadcast and if one CPU 2328 * goes into machine check the others follow quickly, so we don't 2329 * expect a machine check to cause undue problems during to code 2330 * patching. 2331 */ 2332 2333 /* 2334 * Make sure to set (artificial) features depending on used paravirt 2335 * functions which can later influence alternative patching. 2336 */ 2337 paravirt_set_cap(); 2338 2339 /* Keep CET-IBT disabled until caller/callee are patched */ 2340 ibt = ibt_save(/*disable*/ true); 2341 2342 __apply_fineibt(__retpoline_sites, __retpoline_sites_end, 2343 __cfi_sites, __cfi_sites_end, true); 2344 2345 /* 2346 * Rewrite the retpolines, must be done before alternatives since 2347 * those can rewrite the retpoline thunks. 2348 */ 2349 apply_retpolines(__retpoline_sites, __retpoline_sites_end); 2350 apply_returns(__return_sites, __return_sites_end); 2351 2352 /* Make potential last thunk page read-only. */ > 2353 if (its_page) > 2354 its_set_kernel_ro(its_page); 2355 its_page = NULL; 2356 2357 /* 2358 * Adjust all CALL instructions to point to func()-10, including 2359 * those in .altinstr_replacement. 2360 */ 2361 callthunks_patch_builtin_calls(); 2362 2363 apply_alternatives(__alt_instructions, __alt_instructions_end); 2364 2365 /* 2366 * Seal all functions that do not have their address taken. 2367 */ 2368 apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end); 2369 2370 ibt_restore(ibt); 2371 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-06-11 9:30 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-28 12:35 [PATCH 0/3] x86: Fix some bugs related to ITS mitigation Juergen Gross 2025-05-28 12:35 ` [PATCH 1/3] x86/execmem: don't use PAGE_KERNEL protection for code pages Juergen Gross 2025-05-28 17:27 ` Mike Rapoport 2025-05-28 18:22 ` Jürgen Groß 2025-05-30 7:44 ` Peter Zijlstra 2025-05-28 12:35 ` [PATCH 2/3] x86/mm/pat: don't collapse pages without PSE set Juergen Gross 2025-06-11 9:30 ` [tip: x86/urgent] " tip-bot2 for Juergen Gross 2025-05-28 12:35 ` [PATCH 3/3] x86/alternative: make kernel ITS thunks read-only Juergen Gross 2025-05-28 13:10 ` Peter Zijlstra 2025-05-28 13:19 ` Jürgen Groß 2025-05-28 13:22 ` Peter Zijlstra 2025-05-28 13:30 ` Jürgen Groß 2025-05-28 15:58 ` Peter Zijlstra 2025-05-28 16:17 ` Peter Zijlstra 2025-05-28 17:24 ` Mike Rapoport 2025-05-28 17:31 ` Mike Rapoport 2025-06-03 11:17 ` Mike Rapoport 2025-05-29 4:09 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).