Skip to content

Commit d2cf390

Browse files
committed
module: switch to execmem API for remapping as RW and restoring ROX
jira LE-4694 Rebuild_History Non-Buildable kernel-6.12.0-55.43.1.el10_0 commit-author Mike Rapoport (Microsoft) <rppt@kernel.org> commit c287c07 Instead of using writable copy for module text sections, temporarily remap the memory allocated from execmem's ROX cache as writable and restore its ROX permissions after the module is formed. This will allow removing nasty games with writable copy in alternatives patching on x86. Signed-off-by: "Mike Rapoport (Microsoft)" <rppt@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20250126074733.1384926-7-rppt@kernel.org (cherry picked from commit c287c07) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent e34d43f commit d2cf390

File tree

4 files changed

+27
-72
lines changed

4 files changed

+27
-72
lines changed

include/linux/module.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,6 @@ enum mod_mem_type {
367367

368368
struct module_memory {
369369
void *base;
370-
void *rw_copy;
371370
bool is_rox;
372371
unsigned int size;
373372

@@ -770,14 +769,9 @@ static inline bool is_livepatch_module(struct module *mod)
770769

771770
void set_module_sig_enforced(void);
772771

773-
void *__module_writable_address(struct module *mod, void *loc);
774-
775772
static inline void *module_writable_address(struct module *mod, void *loc)
776773
{
777-
if (!IS_ENABLED(CONFIG_ARCH_HAS_EXECMEM_ROX) || !mod ||
778-
mod->state != MODULE_STATE_UNFORMED)
779-
return loc;
780-
return __module_writable_address(mod, loc);
774+
return loc;
781775
}
782776

783777
#else /* !CONFIG_MODULES... */

include/linux/moduleloader.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,6 @@ int module_finalize(const Elf_Ehdr *hdr,
108108
const Elf_Shdr *sechdrs,
109109
struct module *mod);
110110

111-
int module_post_finalize(const Elf_Ehdr *hdr,
112-
const Elf_Shdr *sechdrs,
113-
struct module *mod);
114-
115111
#ifdef CONFIG_MODULES
116112
void flush_module_init_free_work(void);
117113
#else

kernel/module/main.c

Lines changed: 21 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,18 +1193,6 @@ void __weak module_arch_freeing_init(struct module *mod)
11931193
{
11941194
}
11951195

1196-
void *__module_writable_address(struct module *mod, void *loc)
1197-
{
1198-
for_class_mod_mem_type(type, text) {
1199-
struct module_memory *mem = &mod->mem[type];
1200-
1201-
if (loc >= mem->base && loc < mem->base + mem->size)
1202-
return loc + (mem->rw_copy - mem->base);
1203-
}
1204-
1205-
return loc;
1206-
}
1207-
12081196
static int module_memory_alloc(struct module *mod, enum mod_mem_type type)
12091197
{
12101198
unsigned int size = PAGE_ALIGN(mod->mem[type].size);
@@ -1222,21 +1210,15 @@ static int module_memory_alloc(struct module *mod, enum mod_mem_type type)
12221210
if (!ptr)
12231211
return -ENOMEM;
12241212

1225-
mod->mem[type].base = ptr;
1226-
12271213
if (execmem_is_rox(execmem_type)) {
1228-
ptr = vzalloc(size);
1214+
int err = execmem_make_temp_rw(ptr, size);
12291215

1230-
if (!ptr) {
1231-
execmem_free(mod->mem[type].base);
1216+
if (err) {
1217+
execmem_free(ptr);
12321218
return -ENOMEM;
12331219
}
12341220

1235-
mod->mem[type].rw_copy = ptr;
12361221
mod->mem[type].is_rox = true;
1237-
} else {
1238-
mod->mem[type].rw_copy = mod->mem[type].base;
1239-
memset(mod->mem[type].base, 0, size);
12401222
}
12411223

12421224
/*
@@ -1252,16 +1234,26 @@ static int module_memory_alloc(struct module *mod, enum mod_mem_type type)
12521234
*/
12531235
kmemleak_not_leak(ptr);
12541236

1237+
memset(ptr, 0, size);
1238+
mod->mem[type].base = ptr;
1239+
12551240
return 0;
12561241
}
12571242

1243+
static void module_memory_restore_rox(struct module *mod)
1244+
{
1245+
for_class_mod_mem_type(type, text) {
1246+
struct module_memory *mem = &mod->mem[type];
1247+
1248+
if (mem->is_rox)
1249+
execmem_restore_rox(mem->base, mem->size);
1250+
}
1251+
}
1252+
12581253
static void module_memory_free(struct module *mod, enum mod_mem_type type)
12591254
{
12601255
struct module_memory *mem = &mod->mem[type];
12611256

1262-
if (mem->is_rox)
1263-
vfree(mem->rw_copy);
1264-
12651257
execmem_free(mem->base);
12661258
}
12671259

@@ -2290,7 +2282,6 @@ static int move_module(struct module *mod, struct load_info *info)
22902282
for_each_mod_mem_type(type) {
22912283
if (!mod->mem[type].size) {
22922284
mod->mem[type].base = NULL;
2293-
mod->mem[type].rw_copy = NULL;
22942285
continue;
22952286
}
22962287

@@ -2307,7 +2298,6 @@ static int move_module(struct module *mod, struct load_info *info)
23072298
void *dest;
23082299
Elf_Shdr *shdr = &info->sechdrs[i];
23092300
const char *sname;
2310-
unsigned long addr;
23112301

23122302
if (!(shdr->sh_flags & SHF_ALLOC))
23132303
continue;
@@ -2328,14 +2318,12 @@ static int move_module(struct module *mod, struct load_info *info)
23282318
ret = PTR_ERR(dest);
23292319
goto out_err;
23302320
}
2331-
addr = (unsigned long)dest;
23322321
codetag_section_found = true;
23332322
} else {
23342323
enum mod_mem_type type = shdr->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT;
23352324
unsigned long offset = shdr->sh_entsize & SH_ENTSIZE_OFFSET_MASK;
23362325

2337-
addr = (unsigned long)mod->mem[type].base + offset;
2338-
dest = mod->mem[type].rw_copy + offset;
2326+
dest = mod->mem[type].base + offset;
23392327
}
23402328

23412329
if (shdr->sh_type != SHT_NOBITS) {
@@ -2358,13 +2346,14 @@ static int move_module(struct module *mod, struct load_info *info)
23582346
* users of info can keep taking advantage and using the newly
23592347
* minted official memory area.
23602348
*/
2361-
shdr->sh_addr = addr;
2349+
shdr->sh_addr = (unsigned long)dest;
23622350
pr_debug("\t0x%lx 0x%.8lx %s\n", (long)shdr->sh_addr,
23632351
(long)shdr->sh_size, info->secstrings + shdr->sh_name);
23642352
}
23652353

23662354
return 0;
23672355
out_err:
2356+
module_memory_restore_rox(mod);
23682357
for (t--; t >= 0; t--)
23692358
module_memory_free(mod, t);
23702359
if (codetag_section_found)
@@ -2511,17 +2500,8 @@ int __weak module_finalize(const Elf_Ehdr *hdr,
25112500
return 0;
25122501
}
25132502

2514-
int __weak module_post_finalize(const Elf_Ehdr *hdr,
2515-
const Elf_Shdr *sechdrs,
2516-
struct module *me)
2517-
{
2518-
return 0;
2519-
}
2520-
25212503
static int post_relocation(struct module *mod, const struct load_info *info)
25222504
{
2523-
int ret;
2524-
25252505
/* Sort exception table now relocations are done. */
25262506
sort_extable(mod->extable, mod->extable + mod->num_exentries);
25272507

@@ -2533,24 +2513,7 @@ static int post_relocation(struct module *mod, const struct load_info *info)
25332513
add_kallsyms(mod, info);
25342514

25352515
/* Arch-specific module finalizing. */
2536-
ret = module_finalize(info->hdr, info->sechdrs, mod);
2537-
if (ret)
2538-
return ret;
2539-
2540-
for_each_mod_mem_type(type) {
2541-
struct module_memory *mem = &mod->mem[type];
2542-
2543-
if (mem->is_rox) {
2544-
if (!execmem_update_copy(mem->base, mem->rw_copy,
2545-
mem->size))
2546-
return -ENOMEM;
2547-
2548-
vfree(mem->rw_copy);
2549-
mem->rw_copy = NULL;
2550-
}
2551-
}
2552-
2553-
return module_post_finalize(info->hdr, info->sechdrs, mod);
2516+
return module_finalize(info->hdr, info->sechdrs, mod);
25542517
}
25552518

25562519
/* Call module constructors. */
@@ -3151,6 +3114,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
31513114
mod->mem[type].size);
31523115
}
31533116

3117+
module_memory_restore_rox(mod);
31543118
module_deallocate(mod, info);
31553119
free_copy:
31563120
/*

kernel/module/strict_rwx.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/mm.h>
1010
#include <linux/vmalloc.h>
1111
#include <linux/set_memory.h>
12+
#include <linux/execmem.h>
1213
#include "internal.h"
1314

1415
static int module_set_memory(const struct module *mod, enum mod_mem_type type,
@@ -32,12 +33,12 @@ static int module_set_memory(const struct module *mod, enum mod_mem_type type,
3233
int module_enable_text_rox(const struct module *mod)
3334
{
3435
for_class_mod_mem_type(type, text) {
36+
const struct module_memory *mem = &mod->mem[type];
3537
int ret;
3638

37-
if (mod->mem[type].is_rox)
38-
continue;
39-
40-
if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
39+
if (mem->is_rox)
40+
ret = execmem_restore_rox(mem->base, mem->size);
41+
else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
4142
ret = module_set_memory(mod, type, set_memory_rox);
4243
else
4344
ret = module_set_memory(mod, type, set_memory_x);

0 commit comments

Comments
 (0)