mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-28 00:19:36 +00:00
x86/its: explicitly manage permissions for ITS pages
execmem_alloc() sets permissions differently depending on the kernel
configuration, CPU support for PSE and whether a page is allocated
before or after mark_rodata_ro().
Add tracking for pages allocated for ITS when patching the core kernel
and make sure the permissions for ITS pages are explicitly managed for
both kernel and module allocations.
Fixes: 872df34d7c
("x86/its: Use dynamic thunks for indirect branches")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20250603111446.2609381-5-rppt@kernel.org
This commit is contained in:
parent
0b0cae7119
commit
a82b26451d
@ -116,6 +116,24 @@ static struct module *its_mod;
|
||||
#endif
|
||||
static void *its_page;
|
||||
static unsigned int its_offset;
|
||||
struct its_array its_pages;
|
||||
|
||||
static void *__its_alloc(struct its_array *pages)
|
||||
{
|
||||
void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
void *tmp = krealloc(pages->pages, (pages->num+1) * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
pages->pages = tmp;
|
||||
pages->pages[pages->num++] = page;
|
||||
|
||||
return no_free_ptr(page);
|
||||
}
|
||||
|
||||
/* Initialize a thunk with the "jmp *reg; int3" instructions. */
|
||||
static void *its_init_thunk(void *thunk, int reg)
|
||||
@ -151,6 +169,21 @@ static void *its_init_thunk(void *thunk, int reg)
|
||||
return thunk + offset;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void its_fini_core(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
|
||||
its_pages_protect(&its_pages);
|
||||
kfree(its_pages.pages);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
void its_init_mod(struct module *mod)
|
||||
{
|
||||
@ -173,10 +206,8 @@ void its_fini_mod(struct module *mod)
|
||||
its_page = NULL;
|
||||
mutex_unlock(&text_mutex);
|
||||
|
||||
for (int i = 0; i < mod->arch.its_pages.num; i++) {
|
||||
void *page = mod->arch.its_pages.pages[i];
|
||||
execmem_restore_rox(page, PAGE_SIZE);
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
|
||||
its_pages_protect(&mod->arch.its_pages);
|
||||
}
|
||||
|
||||
void its_free_mod(struct module *mod)
|
||||
@ -194,28 +225,23 @@ void its_free_mod(struct module *mod)
|
||||
|
||||
static void *its_alloc(void)
|
||||
{
|
||||
void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE);
|
||||
struct its_array *pages = &its_pages;
|
||||
void *page;
|
||||
|
||||
#ifdef CONFIG_MODULE
|
||||
if (its_mod)
|
||||
pages = &its_mod->arch.its_pages;
|
||||
#endif
|
||||
|
||||
page = __its_alloc(pages);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
if (its_mod) {
|
||||
struct its_array *pages = &its_mod->arch.its_pages;
|
||||
void *tmp = krealloc(pages->pages,
|
||||
(pages->num+1) * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
execmem_make_temp_rw(page, PAGE_SIZE);
|
||||
if (pages == &its_pages)
|
||||
set_memory_x((unsigned long)page, 1);
|
||||
|
||||
pages->pages = tmp;
|
||||
pages->pages[pages->num++] = page;
|
||||
|
||||
execmem_make_temp_rw(page, PAGE_SIZE);
|
||||
}
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
return no_free_ptr(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
static void *its_allocate_thunk(int reg)
|
||||
@ -269,7 +295,9 @@ u8 *its_static_thunk(int reg)
|
||||
return thunk;
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
static inline void its_fini_core(void) {}
|
||||
#endif /* CONFIG_MITIGATION_ITS */
|
||||
|
||||
/*
|
||||
* Nomenclature for variable names to simplify and clarify this code and ease
|
||||
@ -2339,6 +2367,8 @@ void __init alternative_instructions(void)
|
||||
apply_retpolines(__retpoline_sites, __retpoline_sites_end);
|
||||
apply_returns(__return_sites, __return_sites_end);
|
||||
|
||||
its_fini_core();
|
||||
|
||||
/*
|
||||
* Adjust all CALL instructions to point to func()-10, including
|
||||
* those in .altinstr_replacement.
|
||||
|
Loading…
Reference in New Issue
Block a user