Commit ef505058 authored by Christophe Leroy's avatar Christophe Leroy Committed by Luis Chamberlain
Browse files

module: Rework layout alignment to avoid BUG_ON()s



Perform layout alignment verification up front and WARN_ON()
and fail module loading instead of crashing the machine.

Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
parent 32a08c17
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ void module_enable_nx(const struct module *mod);
void module_enable_x(const struct module *mod);
int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
				char *secstrings, struct module *mod);
bool module_check_misalignment(const struct module *mod);

#ifdef CONFIG_MODULE_SIG
int module_sig_check(struct load_info *info, int flags);
+5 −0
Original line number Diff line number Diff line
@@ -2550,6 +2550,9 @@ static int complete_formation(struct module *mod, struct load_info *info)
	/* This relies on module_mutex for list integrity. */
	module_bug_finalize(info->hdr, info->sechdrs, mod);

	if (module_check_misalignment(mod))
		goto out_misaligned;

	module_enable_ro(mod, false);
	module_enable_nx(mod);
	module_enable_x(mod);
@@ -2563,6 +2566,8 @@ static int complete_formation(struct module *mod, struct load_info *info)

	return 0;

out_misaligned:
	err = -EINVAL;
out:
	mutex_unlock(&module_mutex);
	return err;
+18 −9
Original line number Diff line number Diff line
@@ -42,9 +42,6 @@ static void frob_text(const struct module_layout *layout,
static void frob_rodata(const struct module_layout *layout,
		 int (*set_memory)(unsigned long start, int num_pages))
{
	BUG_ON(!PAGE_ALIGNED(layout->base));
	BUG_ON(!PAGE_ALIGNED(layout->text_size));
	BUG_ON(!PAGE_ALIGNED(layout->ro_size));
	set_memory((unsigned long)layout->base + layout->text_size,
		   (layout->ro_size - layout->text_size) >> PAGE_SHIFT);
}
@@ -52,9 +49,6 @@ static void frob_rodata(const struct module_layout *layout,
static void frob_ro_after_init(const struct module_layout *layout,
			int (*set_memory)(unsigned long start, int num_pages))
{
	BUG_ON(!PAGE_ALIGNED(layout->base));
	BUG_ON(!PAGE_ALIGNED(layout->ro_size));
	BUG_ON(!PAGE_ALIGNED(layout->ro_after_init_size));
	set_memory((unsigned long)layout->base + layout->ro_size,
		   (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
}
@@ -62,13 +56,28 @@ static void frob_ro_after_init(const struct module_layout *layout,
static void frob_writable_data(const struct module_layout *layout,
			int (*set_memory)(unsigned long start, int num_pages))
{
	BUG_ON(!PAGE_ALIGNED(layout->base));
	BUG_ON(!PAGE_ALIGNED(layout->ro_after_init_size));
	BUG_ON(!PAGE_ALIGNED(layout->size));
	set_memory((unsigned long)layout->base + layout->ro_after_init_size,
		   (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
}

static bool layout_check_misalignment(const struct module_layout *layout)
{
	return WARN_ON(!PAGE_ALIGNED(layout->base)) ||
	       WARN_ON(!PAGE_ALIGNED(layout->text_size)) ||
	       WARN_ON(!PAGE_ALIGNED(layout->ro_size)) ||
	       WARN_ON(!PAGE_ALIGNED(layout->ro_after_init_size)) ||
	       WARN_ON(!PAGE_ALIGNED(layout->size));
}

bool module_check_misalignment(const struct module *mod)
{
	if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
		return false;

	return layout_check_misalignment(&mod->core_layout) ||
	       layout_check_misalignment(&mod->init_layout);
}

void module_enable_x(const struct module *mod)
{
	if (!PAGE_ALIGNED(mod->core_layout.base) ||