summaryrefslogtreecommitdiffstats
path: root/kernel/module/main.c
diff options
context:
space:
mode:
authorChristophe Leroy <christophe.leroy@csgroup.eu>2022-02-23 13:02:13 +0100
committerLuis Chamberlain <mcgrof@kernel.org>2022-04-05 08:43:05 -0700
commit6ab9942c44b2d213a16b2620e4baf0223122222f (patch)
tree0ca6816cea5a0928994fa94ae4868df9b4f48b56 /kernel/module/main.c
parent446d55666d5599ca58c1ceac25ce4b5191e70835 (diff)
downloadlinux-6ab9942c44b2d213a16b2620e4baf0223122222f.tar.bz2
module: Introduce data_layout
In order to allow separation of data from text, add another layout, called data_layout. For architectures requesting separation of text and data, only text will go in core_layout and data will go in data_layout. For architectures which keep text and data together, make data_layout an alias of core_layout, that way data_layout can be used for all data manipulations, regardless of whether data is in core_layout or data_layout. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Diffstat (limited to 'kernel/module/main.c')
-rw-r--r--kernel/module/main.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 392ac847d90a..78658283408d 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1190,7 +1190,7 @@ static void free_module(struct module *mod)
percpu_modfree(mod);
/* Free lock-classes; relies on the preceding sync_rcu(). */
- lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size);
+ lockdep_free_key_range(mod->data_layout.base, mod->data_layout.size);
/* Finally, free the core (containing the module structure) */
module_memfree(mod->core_layout.base);
@@ -1431,13 +1431,15 @@ static void layout_sections(struct module *mod, struct load_info *info)
for (i = 0; i < info->hdr->e_shnum; ++i) {
Elf_Shdr *s = &info->sechdrs[i];
const char *sname = info->secstrings + s->sh_name;
+ unsigned int *sizep;
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL
|| module_init_layout_section(sname))
continue;
- s->sh_entsize = module_get_offset(mod, &mod->core_layout.size, s, i);
+ sizep = m ? &mod->data_layout.size : &mod->core_layout.size;
+ s->sh_entsize = module_get_offset(mod, sizep, s, i);
pr_debug("\t%s\n", sname);
}
switch (m) {
@@ -1446,15 +1448,15 @@ static void layout_sections(struct module *mod, struct load_info *info)
mod->core_layout.text_size = mod->core_layout.size;
break;
case 1: /* RO: text and ro-data */
- mod->core_layout.size = strict_align(mod->core_layout.size);
- mod->core_layout.ro_size = mod->core_layout.size;
+ mod->data_layout.size = strict_align(mod->data_layout.size);
+ mod->data_layout.ro_size = mod->data_layout.size;
break;
case 2: /* RO after init */
- mod->core_layout.size = strict_align(mod->core_layout.size);
- mod->core_layout.ro_after_init_size = mod->core_layout.size;
+ mod->data_layout.size = strict_align(mod->data_layout.size);
+ mod->data_layout.ro_after_init_size = mod->data_layout.size;
break;
case 4: /* whole core */
- mod->core_layout.size = strict_align(mod->core_layout.size);
+ mod->data_layout.size = strict_align(mod->data_layout.size);
break;
}
}
@@ -2134,6 +2136,8 @@ static int move_module(struct module *mod, struct load_info *info)
if (shdr->sh_entsize & INIT_OFFSET_MASK)
dest = mod->init_layout.base
+ (shdr->sh_entsize & ~INIT_OFFSET_MASK);
+ else if (!(shdr->sh_flags & SHF_EXECINSTR))
+ dest = mod->data_layout.base + shdr->sh_entsize;
else
dest = mod->core_layout.base + shdr->sh_entsize;
@@ -2829,7 +2833,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
mutex_unlock(&module_mutex);
free_module:
/* Free lock-classes; relies on the preceding sync_rcu() */
- lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size);
+ lockdep_free_key_range(mod->data_layout.base, mod->data_layout.size);
module_deallocate(mod, info);
free_copy: