Skip to content

Commit 01dc038

Browse files
chleroymcgrof
authored andcommitted
module: Add CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
Add CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC to allow architectures to request having modules data in vmalloc area instead of module area. This is required on powerpc book3s/32 in order to set data non executable, because it is not possible to set executability on page basis, this is done per 256 Mbytes segments. The module area has exec right, vmalloc area has noexec. This can also be useful on other powerpc/32 in order to maximize the chance of code being close enough to kernel core to avoid branch trampolines. Cc: Jason Wessel <[email protected]> Acked-by: Daniel Thompson <[email protected]> Cc: Douglas Anderson <[email protected]> Signed-off-by: Christophe Leroy <[email protected]> [mcgrof: rebased in light of kernel/module/kdb.c move] Signed-off-by: Luis Chamberlain <[email protected]>
1 parent 6ab9942 commit 01dc038

File tree

8 files changed

+96
-6
lines changed

8 files changed

+96
-6
lines changed

arch/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,12 @@ config MODULES_USE_ELF_REL
888888
Modules only use ELF REL relocations. Modules with ELF RELA
889889
relocations will give an error.
890890

891+
config ARCH_WANTS_MODULES_DATA_IN_VMALLOC
892+
bool
893+
help
894+
For architectures like powerpc/32 which have constraints on module
895+
allocation and need to allocate module data outside of module area.
896+
891897
config HAVE_IRQ_EXIT_ON_IRQ_STACK
892898
bool
893899
help

include/linux/module.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,9 @@ struct module {
422422
/* Core layout: rbtree is accessed frequently, so keep together. */
423423
struct module_layout core_layout __module_layout_align;
424424
struct module_layout init_layout;
425+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
426+
struct module_layout data_layout;
427+
#endif
425428

426429
/* Arch-specific module values */
427430
struct mod_arch_specific arch;
@@ -569,6 +572,11 @@ bool is_module_text_address(unsigned long addr);
569572
static inline bool within_module_core(unsigned long addr,
570573
const struct module *mod)
571574
{
575+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
576+
if ((unsigned long)mod->data_layout.base <= addr &&
577+
addr < (unsigned long)mod->data_layout.base + mod->data_layout.size)
578+
return true;
579+
#endif
572580
return (unsigned long)mod->core_layout.base <= addr &&
573581
addr < (unsigned long)mod->core_layout.base + mod->core_layout.size;
574582
}

kernel/module/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
/* Maximum number of characters written by module_flags() */
2121
#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
2222

23+
#ifndef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
2324
#define data_layout core_layout
25+
#endif
2426

2527
/*
2628
* Modules' sections will be aligned on page boundaries
@@ -154,6 +156,7 @@ struct mod_tree_root {
154156
};
155157

156158
extern struct mod_tree_root mod_tree;
159+
extern struct mod_tree_root mod_data_tree;
157160

158161
#ifdef CONFIG_MODULES_TREE_LOOKUP
159162
void mod_tree_insert(struct module *mod);

kernel/module/kdb.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ int kdb_lsmod(int argc, const char **argv)
2626
if (mod->state == MODULE_STATE_UNFORMED)
2727
continue;
2828

29-
kdb_printf("%-20s%8u 0x%px ", mod->name,
30-
mod->core_layout.size, (void *)mod);
29+
kdb_printf("%-20s%8u", mod->name, mod->core_layout.size);
30+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
31+
kdb_printf("/%8u", mod->data_layout.size);
32+
#endif
33+
kdb_printf(" 0x%px ", (void *)mod);
3134
#ifdef CONFIG_MODULE_UNLOAD
3235
kdb_printf("%4d ", module_refcount(mod));
3336
#endif
@@ -38,6 +41,9 @@ int kdb_lsmod(int argc, const char **argv)
3841
else
3942
kdb_printf(" (Live)");
4043
kdb_printf(" 0x%px", mod->core_layout.base);
44+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
45+
kdb_printf("/0x%px", mod->data_layout.base);
46+
#endif
4147

4248
#ifdef CONFIG_MODULE_UNLOAD
4349
{

kernel/module/main.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ struct mod_tree_root mod_tree __cacheline_aligned = {
7878
.addr_min = -1UL,
7979
};
8080

81+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
82+
struct mod_tree_root mod_data_tree __cacheline_aligned = {
83+
.addr_min = -1UL,
84+
};
85+
#endif
86+
8187
#define module_addr_min mod_tree.addr_min
8288
#define module_addr_max mod_tree.addr_max
8389

@@ -107,6 +113,9 @@ static void mod_update_bounds(struct module *mod)
107113
__mod_update_bounds(mod->core_layout.base, mod->core_layout.size, &mod_tree);
108114
if (mod->init_layout.size)
109115
__mod_update_bounds(mod->init_layout.base, mod->init_layout.size, &mod_tree);
116+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
117+
__mod_update_bounds(mod->data_layout.base, mod->data_layout.size, &mod_data_tree);
118+
#endif
110119
}
111120

112121
static void module_assert_mutex_or_preempt(void)
@@ -940,6 +949,17 @@ static ssize_t show_coresize(struct module_attribute *mattr,
940949
static struct module_attribute modinfo_coresize =
941950
__ATTR(coresize, 0444, show_coresize, NULL);
942951

952+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
953+
static ssize_t show_datasize(struct module_attribute *mattr,
954+
struct module_kobject *mk, char *buffer)
955+
{
956+
return sprintf(buffer, "%u\n", mk->mod->data_layout.size);
957+
}
958+
959+
static struct module_attribute modinfo_datasize =
960+
__ATTR(datasize, 0444, show_datasize, NULL);
961+
#endif
962+
943963
static ssize_t show_initsize(struct module_attribute *mattr,
944964
struct module_kobject *mk, char *buffer)
945965
{
@@ -968,6 +988,9 @@ struct module_attribute *modinfo_attrs[] = {
968988
&modinfo_srcversion,
969989
&modinfo_initstate,
970990
&modinfo_coresize,
991+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
992+
&modinfo_datasize,
993+
#endif
971994
&modinfo_initsize,
972995
&modinfo_taint,
973996
#ifdef CONFIG_MODULE_UNLOAD
@@ -1194,6 +1217,9 @@ static void free_module(struct module *mod)
11941217

11951218
/* Finally, free the core (containing the module structure) */
11961219
module_memfree(mod->core_layout.base);
1220+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
1221+
vfree(mod->data_layout.base);
1222+
#endif
11971223
}
11981224

11991225
void *__symbol_get(const char *symbol)
@@ -2124,6 +2150,24 @@ static int move_module(struct module *mod, struct load_info *info)
21242150
} else
21252151
mod->init_layout.base = NULL;
21262152

2153+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
2154+
/* Do the allocs. */
2155+
ptr = vmalloc(mod->data_layout.size);
2156+
/*
2157+
* The pointer to this block is stored in the module structure
2158+
* which is inside the block. Just mark it as not being a
2159+
* leak.
2160+
*/
2161+
kmemleak_not_leak(ptr);
2162+
if (!ptr) {
2163+
module_memfree(mod->core_layout.base);
2164+
module_memfree(mod->init_layout.base);
2165+
return -ENOMEM;
2166+
}
2167+
2168+
memset(ptr, 0, mod->data_layout.size);
2169+
mod->data_layout.base = ptr;
2170+
#endif
21272171
/* Transfer each section which specifies SHF_ALLOC */
21282172
pr_debug("final section addresses:\n");
21292173
for (i = 0; i < info->hdr->e_shnum; i++) {
@@ -2299,6 +2343,9 @@ static void module_deallocate(struct module *mod, struct load_info *info)
22992343
module_arch_freeing_init(mod);
23002344
module_memfree(mod->init_layout.base);
23012345
module_memfree(mod->core_layout.base);
2346+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
2347+
vfree(mod->data_layout.base);
2348+
#endif
23022349
}
23032350

23042351
int __weak module_finalize(const Elf_Ehdr *hdr,
@@ -3015,13 +3062,20 @@ bool is_module_address(unsigned long addr)
30153062
struct module *__module_address(unsigned long addr)
30163063
{
30173064
struct module *mod;
3065+
struct mod_tree_root *tree;
30183066

3019-
if (addr < module_addr_min || addr > module_addr_max)
3067+
if (addr >= mod_tree.addr_min && addr <= mod_tree.addr_max)
3068+
tree = &mod_tree;
3069+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
3070+
else if (addr >= mod_data_tree.addr_min && addr <= mod_data_tree.addr_max)
3071+
tree = &mod_data_tree;
3072+
#endif
3073+
else
30203074
return NULL;
30213075

30223076
module_assert_mutex_or_preempt();
30233077

3024-
mod = mod_find(addr, &mod_tree);
3078+
mod = mod_find(addr, tree);
30253079
if (mod) {
30263080
BUG_ON(!within_module(addr, mod));
30273081
if (mod->state == MODULE_STATE_UNFORMED)

kernel/module/procfs.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,17 @@ static int m_show(struct seq_file *m, void *p)
6767
struct module *mod = list_entry(p, struct module, list);
6868
char buf[MODULE_FLAGS_BUF_SIZE];
6969
void *value;
70+
unsigned int size;
7071

7172
/* We always ignore unformed modules. */
7273
if (mod->state == MODULE_STATE_UNFORMED)
7374
return 0;
7475

75-
seq_printf(m, "%s %u",
76-
mod->name, mod->init_layout.size + mod->core_layout.size);
76+
size = mod->init_layout.size + mod->core_layout.size;
77+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
78+
size += mod->data_layout.size;
79+
#endif
80+
seq_printf(m, "%s %u", mod->name, size);
7781
print_unload_info(m, mod);
7882

7983
/* Informative for users. */

kernel/module/strict_rwx.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ bool module_check_misalignment(const struct module *mod)
7575
return false;
7676

7777
return layout_check_misalignment(&mod->core_layout) ||
78+
layout_check_misalignment(&mod->data_layout) ||
7879
layout_check_misalignment(&mod->init_layout);
7980
}
8081

kernel/module/tree_lookup.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ void mod_tree_insert(struct module *mod)
8383
__mod_tree_insert(&mod->core_layout.mtn, &mod_tree);
8484
if (mod->init_layout.size)
8585
__mod_tree_insert(&mod->init_layout.mtn, &mod_tree);
86+
87+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
88+
mod->data_layout.mtn.mod = mod;
89+
__mod_tree_insert(&mod->data_layout.mtn, &mod_data_tree);
90+
#endif
8691
}
8792

8893
void mod_tree_remove_init(struct module *mod)
@@ -95,6 +100,9 @@ void mod_tree_remove(struct module *mod)
95100
{
96101
__mod_tree_remove(&mod->core_layout.mtn, &mod_tree);
97102
mod_tree_remove_init(mod);
103+
#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
104+
__mod_tree_remove(&mod->data_layout.mtn, &mod_data_tree);
105+
#endif
98106
}
99107

100108
struct module *mod_find(unsigned long addr, struct mod_tree_root *tree)

0 commit comments

Comments
 (0)