Skip to content

Commit a82b264

Browse files
author
Peter Zijlstra (Intel)
committed
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: 872df34 ("x86/its: Use dynamic thunks for indirect branches") Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Co-developed-by: Mike Rapoport (Microsoft) <[email protected]> Signed-off-by: Mike Rapoport (Microsoft) <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Nikolay Borisov <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 0b0cae7 commit a82b264

File tree

1 file changed

+52
-22
lines changed

1 file changed

+52
-22
lines changed

arch/x86/kernel/alternative.c

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,24 @@ static struct module *its_mod;
116116
#endif
117117
static void *its_page;
118118
static unsigned int its_offset;
119+
struct its_array its_pages;
120+
121+
static void *__its_alloc(struct its_array *pages)
122+
{
123+
void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE);
124+
if (!page)
125+
return NULL;
126+
127+
void *tmp = krealloc(pages->pages, (pages->num+1) * sizeof(void *),
128+
GFP_KERNEL);
129+
if (!tmp)
130+
return NULL;
131+
132+
pages->pages = tmp;
133+
pages->pages[pages->num++] = page;
134+
135+
return no_free_ptr(page);
136+
}
119137

120138
/* Initialize a thunk with the "jmp *reg; int3" instructions. */
121139
static void *its_init_thunk(void *thunk, int reg)
@@ -151,6 +169,21 @@ static void *its_init_thunk(void *thunk, int reg)
151169
return thunk + offset;
152170
}
153171

172+
static void its_pages_protect(struct its_array *pages)
173+
{
174+
for (int i = 0; i < pages->num; i++) {
175+
void *page = pages->pages[i];
176+
execmem_restore_rox(page, PAGE_SIZE);
177+
}
178+
}
179+
180+
static void its_fini_core(void)
181+
{
182+
if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
183+
its_pages_protect(&its_pages);
184+
kfree(its_pages.pages);
185+
}
186+
154187
#ifdef CONFIG_MODULES
155188
void its_init_mod(struct module *mod)
156189
{
@@ -173,10 +206,8 @@ void its_fini_mod(struct module *mod)
173206
its_page = NULL;
174207
mutex_unlock(&text_mutex);
175208

176-
for (int i = 0; i < mod->arch.its_pages.num; i++) {
177-
void *page = mod->arch.its_pages.pages[i];
178-
execmem_restore_rox(page, PAGE_SIZE);
179-
}
209+
if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
210+
its_pages_protect(&mod->arch.its_pages);
180211
}
181212

182213
void its_free_mod(struct module *mod)
@@ -194,28 +225,23 @@ void its_free_mod(struct module *mod)
194225

195226
static void *its_alloc(void)
196227
{
197-
void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE);
228+
struct its_array *pages = &its_pages;
229+
void *page;
198230

231+
#ifdef CONFIG_MODULE
232+
if (its_mod)
233+
pages = &its_mod->arch.its_pages;
234+
#endif
235+
236+
page = __its_alloc(pages);
199237
if (!page)
200238
return NULL;
201239

202-
#ifdef CONFIG_MODULES
203-
if (its_mod) {
204-
struct its_array *pages = &its_mod->arch.its_pages;
205-
void *tmp = krealloc(pages->pages,
206-
(pages->num+1) * sizeof(void *),
207-
GFP_KERNEL);
208-
if (!tmp)
209-
return NULL;
210-
211-
pages->pages = tmp;
212-
pages->pages[pages->num++] = page;
240+
execmem_make_temp_rw(page, PAGE_SIZE);
241+
if (pages == &its_pages)
242+
set_memory_x((unsigned long)page, 1);
213243

214-
execmem_make_temp_rw(page, PAGE_SIZE);
215-
}
216-
#endif /* CONFIG_MODULES */
217-
218-
return no_free_ptr(page);
244+
return page;
219245
}
220246

221247
static void *its_allocate_thunk(int reg)
@@ -269,7 +295,9 @@ u8 *its_static_thunk(int reg)
269295
return thunk;
270296
}
271297

272-
#endif
298+
#else
299+
static inline void its_fini_core(void) {}
300+
#endif /* CONFIG_MITIGATION_ITS */
273301

274302
/*
275303
* Nomenclature for variable names to simplify and clarify this code and ease
@@ -2339,6 +2367,8 @@ void __init alternative_instructions(void)
23392367
apply_retpolines(__retpoline_sites, __retpoline_sites_end);
23402368
apply_returns(__return_sites, __return_sites_end);
23412369

2370+
its_fini_core();
2371+
23422372
/*
23432373
* Adjust all CALL instructions to point to func()-10, including
23442374
* those in .altinstr_replacement.

0 commit comments

Comments
 (0)