Removed the MODULE_SIG_FORCE-means-no-MODULE_FORCE_LOAD patch.
Only interesting thing here is Jessica's patch to add ro_after_init support to modules. The rest are all trivia. Cheers, Rusty. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXopD9AAoJENkgDmzRrbjxDVEP+waK+E3Y+vJHibLwwCYcVqLG OAkQoFXGqxYAo0faGtGPZczxDH/GVK754y+qugOeQvCgHJqit7qWmIUs5uRgqUMb uKjoUOfCBiVGUsaHfw7RisOP5FXvAk1jkFxBVtywPj6eIonLr9BB4VE813iXnYGG RkVFvAmFxMgq2BY+yjp4IDCGNVEFBq9UrXZ8XY+WGhI1pbxVp9SCUVrLckARDSS4 t5NeVeLCFlNKmw+ElU7zCKaa4Cyloq9lGFBA1ZgchGADRsOrha9VHNRVxR0pHSIG 100SW+nFhncNWqVQ2YgspVe1so993wGnORPpsb+o3dg7mIn2wkj6WhTfAKv/UQ1W 7JUFaRi/rMC8h/njLKvbX+gmEU1d4nnTyZ76UFh+VxU6mbVWYqI44DCLpt+mPT13 JwwqGGCDPnB/28KFmQITYAkdmvAV3u2aZLXJAQPxKVF7/IzklxHHz2ifMEwtPzOh UvuWhjmmPAqncKWXzflxMj8i4C3sPyAs0RDSrMXG7jZJlhguVea+b8bXNhEafR+n GM0btAfGw+VWluyNMlOpigSpJt/n6/hQtzlgBQGn7CeknNwamBe5MLGSN3N9MgL9 WXma9sKn34IqjxtSSP5rJlwTRWHELUZIsKmOnWP4/3gwf1+Fe65ML2cCwp6saeMX ZjEosYxdKo32LiZhRDPR =URwe -----END PGP SIGNATURE----- Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux Pull module updates from Rusty Russell: "The only interesting thing here is Jessica's patch to add ro_after_init support to modules. The rest are all trivia" * tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: extable.h: add stddef.h so "NULL" definition is not implicit modules: add ro_after_init support jump_label: disable preemption around __module_text_address(). exceptions: fork exception table content from module.h into extable.h modules: Add kernel parameter to blacklist modules module: Do a WARN_ON_ONCE() for assert module mutex not held Documentation/module-signing.txt: Note need for version info if reusing a key module: Invalidate signatures on force-loaded modules module: Issue warnings when tainting kernel module: fix redundant test. module: fix noreturn attribute for __module_put_and_exit()
This commit is contained in:
commit
fb1b83d3ff
|
@ -2320,6 +2320,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
Note that if CONFIG_MODULE_SIG_FORCE is set, that
|
||||
is always true, so this option does nothing.
|
||||
|
||||
module_blacklist= [KNL] Do not load a comma-separated list of
|
||||
modules. Useful for debugging problem modules.
|
||||
|
||||
mousedev.tap_time=
|
||||
[MOUSE] Maximum time between finger touching and
|
||||
leaving touchpad surface for touch to be considered
|
||||
|
|
|
@ -271,3 +271,9 @@ Since the private key is used to sign modules, viruses and malware could use
|
|||
the private key to sign modules and compromise the operating system. The
|
||||
private key must be either destroyed or moved to a secure location and not kept
|
||||
in the root node of the kernel source tree.
|
||||
|
||||
If you use the same private key to sign modules for multiple kernel
|
||||
configurations, you must ensure that the module version information is
|
||||
sufficient to prevent loading a module into a different kernel. Either
|
||||
set CONFIG_MODVERSIONS=y or ensure that each configuration has a different
|
||||
kernel release string by changing EXTRAVERSION or CONFIG_LOCALVERSION.
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef _LINUX_EXTABLE_H
|
||||
#define _LINUX_EXTABLE_H
|
||||
|
||||
#include <linux/stddef.h> /* for NULL */
|
||||
|
||||
struct module;
|
||||
struct exception_table_entry;
|
||||
|
||||
const struct exception_table_entry *
|
||||
search_extable(const struct exception_table_entry *first,
|
||||
const struct exception_table_entry *last,
|
||||
unsigned long value);
|
||||
void sort_extable(struct exception_table_entry *start,
|
||||
struct exception_table_entry *finish);
|
||||
void sort_main_extable(void);
|
||||
void trim_init_extable(struct module *m);
|
||||
|
||||
/* Given an address, look for it in the exception tables */
|
||||
const struct exception_table_entry *search_exception_tables(unsigned long add);
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
/* For extable.c to search modules' exception tables. */
|
||||
const struct exception_table_entry *search_module_extables(unsigned long addr);
|
||||
#else
|
||||
static inline const struct exception_table_entry *
|
||||
search_module_extables(unsigned long addr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /*CONFIG_MODULES*/
|
||||
|
||||
#endif /* _LINUX_EXTABLE_H */
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/moduleparam.h>
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/extable.h> /* only as arch move module.h -> extable.h */
|
||||
#include <linux/rbtree_latch.h>
|
||||
|
||||
#include <linux/percpu.h>
|
||||
|
@ -37,6 +38,7 @@ struct modversion_info {
|
|||
};
|
||||
|
||||
struct module;
|
||||
struct exception_table_entry;
|
||||
|
||||
struct module_kobject {
|
||||
struct kobject kobj;
|
||||
|
@ -155,18 +157,6 @@ extern void cleanup_module(void);
|
|||
#define __INITRODATA_OR_MODULE __INITRODATA
|
||||
#endif /*CONFIG_MODULES*/
|
||||
|
||||
/* Archs provide a method of finding the correct exception table. */
|
||||
struct exception_table_entry;
|
||||
|
||||
const struct exception_table_entry *
|
||||
search_extable(const struct exception_table_entry *first,
|
||||
const struct exception_table_entry *last,
|
||||
unsigned long value);
|
||||
void sort_extable(struct exception_table_entry *start,
|
||||
struct exception_table_entry *finish);
|
||||
void sort_main_extable(void);
|
||||
void trim_init_extable(struct module *m);
|
||||
|
||||
/* Generic info of form tag = "info" */
|
||||
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
|
||||
|
||||
|
@ -268,9 +258,6 @@ extern const typeof(name) __mod_##type##__##name##_device_table \
|
|||
* files require multiple MODULE_FIRMWARE() specifiers */
|
||||
#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
|
||||
|
||||
/* Given an address, look for it in the exception tables */
|
||||
const struct exception_table_entry *search_exception_tables(unsigned long add);
|
||||
|
||||
struct notifier_block;
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
@ -311,6 +298,8 @@ struct module_layout {
|
|||
unsigned int text_size;
|
||||
/* Size of RO section of the module (text+rodata) */
|
||||
unsigned int ro_size;
|
||||
/* Size of RO after init section */
|
||||
unsigned int ro_after_init_size;
|
||||
|
||||
#ifdef CONFIG_MODULES_TREE_LOOKUP
|
||||
struct mod_tree_node mtn;
|
||||
|
@ -575,8 +564,8 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
|||
struct module *, unsigned long),
|
||||
void *data);
|
||||
|
||||
extern void __module_put_and_exit(struct module *mod, long code)
|
||||
__attribute__((noreturn));
|
||||
extern void __noreturn __module_put_and_exit(struct module *mod,
|
||||
long code);
|
||||
#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code)
|
||||
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
|
@ -630,9 +619,6 @@ const char *module_address_lookup(unsigned long addr,
|
|||
int lookup_module_symbol_name(unsigned long addr, char *symname);
|
||||
int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
|
||||
|
||||
/* For extable.c to search modules' exception tables. */
|
||||
const struct exception_table_entry *search_module_extables(unsigned long addr);
|
||||
|
||||
int register_module_notifier(struct notifier_block *nb);
|
||||
int unregister_module_notifier(struct notifier_block *nb);
|
||||
|
||||
|
@ -657,13 +643,6 @@ static inline bool is_livepatch_module(struct module *mod)
|
|||
|
||||
#else /* !CONFIG_MODULES... */
|
||||
|
||||
/* Given an address, look for it in the exception tables. */
|
||||
static inline const struct exception_table_entry *
|
||||
search_module_extables(unsigned long addr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct module *__module_address(unsigned long addr)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -788,12 +767,12 @@ extern int module_sysfs_initialized;
|
|||
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
||||
extern void set_all_modules_text_rw(void);
|
||||
extern void set_all_modules_text_ro(void);
|
||||
extern void module_enable_ro(const struct module *mod);
|
||||
extern void module_enable_ro(const struct module *mod, bool after_init);
|
||||
extern void module_disable_ro(const struct module *mod);
|
||||
#else
|
||||
static inline void set_all_modules_text_rw(void) { }
|
||||
static inline void set_all_modules_text_ro(void) { }
|
||||
static inline void module_enable_ro(const struct module *mod) { }
|
||||
static inline void module_enable_ro(const struct module *mod, bool after_init) { }
|
||||
static inline void module_disable_ro(const struct module *mod) { }
|
||||
#endif
|
||||
|
||||
|
|
|
@ -286,6 +286,7 @@ typedef struct elf64_phdr {
|
|||
#define SHF_ALLOC 0x2
|
||||
#define SHF_EXECINSTR 0x4
|
||||
#define SHF_RELA_LIVEPATCH 0x00100000
|
||||
#define SHF_RO_AFTER_INIT 0x00200000
|
||||
#define SHF_MASKPROC 0xf0000000
|
||||
|
||||
/* special section indexes */
|
||||
|
|
|
@ -337,11 +337,14 @@ static int __jump_label_mod_text_reserved(void *start, void *end)
|
|||
{
|
||||
struct module *mod;
|
||||
|
||||
preempt_disable();
|
||||
mod = __module_text_address((unsigned long)start);
|
||||
WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
|
||||
preempt_enable();
|
||||
|
||||
if (!mod)
|
||||
return 0;
|
||||
|
||||
WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
|
||||
|
||||
return __jump_label_text_reserved(mod->jump_entries,
|
||||
mod->jump_entries + mod->num_jump_entries,
|
||||
|
|
|
@ -309,7 +309,7 @@ static int klp_write_object_relocations(struct module *pmod,
|
|||
break;
|
||||
}
|
||||
|
||||
module_enable_ro(pmod);
|
||||
module_enable_ro(pmod, true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
121
kernel/module.c
121
kernel/module.c
|
@ -265,7 +265,7 @@ static void module_assert_mutex_or_preempt(void)
|
|||
if (unlikely(!debug_locks))
|
||||
return;
|
||||
|
||||
WARN_ON(!rcu_read_lock_sched_held() &&
|
||||
WARN_ON_ONCE(!rcu_read_lock_sched_held() &&
|
||||
!lockdep_is_held(&module_mutex));
|
||||
#endif
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
|
|||
* A thread that wants to hold a reference to a module only while it
|
||||
* is running can call this to safely exit. nfsd and lockd use this.
|
||||
*/
|
||||
void __module_put_and_exit(struct module *mod, long code)
|
||||
void __noreturn __module_put_and_exit(struct module *mod, long code)
|
||||
{
|
||||
module_put(mod);
|
||||
do_exit(code);
|
||||
|
@ -1694,8 +1694,7 @@ static int module_add_modinfo_attrs(struct module *mod)
|
|||
|
||||
temp_attr = mod->modinfo_attrs;
|
||||
for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
|
||||
if (!attr->test ||
|
||||
(attr->test && attr->test(mod))) {
|
||||
if (!attr->test || attr->test(mod)) {
|
||||
memcpy(temp_attr, attr, sizeof(*temp_attr));
|
||||
sysfs_attr_init(&temp_attr->attr);
|
||||
error = sysfs_create_file(&mod->mkobj.kobj,
|
||||
|
@ -1859,10 +1858,11 @@ static void mod_sysfs_teardown(struct module *mod)
|
|||
* from modification and any data from execution.
|
||||
*
|
||||
* General layout of module is:
|
||||
* [text] [read-only-data] [writable data]
|
||||
* text_size -----^ ^ ^
|
||||
* ro_size ------------------------| |
|
||||
* size -------------------------------------------|
|
||||
* [text] [read-only-data] [ro-after-init] [writable data]
|
||||
* text_size -----^ ^ ^ ^
|
||||
* ro_size ------------------------| | |
|
||||
* ro_after_init_size -----------------------------| |
|
||||
* size -----------------------------------------------------------|
|
||||
*
|
||||
* These values are always page-aligned (as is base)
|
||||
*/
|
||||
|
@ -1885,14 +1885,24 @@ static void frob_rodata(const struct module_layout *layout,
|
|||
(layout->ro_size - layout->text_size) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static void frob_ro_after_init(const struct module_layout *layout,
|
||||
int (*set_memory)(unsigned long start, int num_pages))
|
||||
{
|
||||
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
|
||||
BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
|
||||
BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
|
||||
set_memory((unsigned long)layout->base + layout->ro_size,
|
||||
(layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static void frob_writable_data(const struct module_layout *layout,
|
||||
int (*set_memory)(unsigned long start, int num_pages))
|
||||
{
|
||||
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
|
||||
BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
|
||||
BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
|
||||
BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1));
|
||||
set_memory((unsigned long)layout->base + layout->ro_size,
|
||||
(layout->size - layout->ro_size) >> PAGE_SHIFT);
|
||||
set_memory((unsigned long)layout->base + layout->ro_after_init_size,
|
||||
(layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/* livepatching wants to disable read-only so it can frob module. */
|
||||
|
@ -1900,21 +1910,26 @@ void module_disable_ro(const struct module *mod)
|
|||
{
|
||||
frob_text(&mod->core_layout, set_memory_rw);
|
||||
frob_rodata(&mod->core_layout, set_memory_rw);
|
||||
frob_ro_after_init(&mod->core_layout, set_memory_rw);
|
||||
frob_text(&mod->init_layout, set_memory_rw);
|
||||
frob_rodata(&mod->init_layout, set_memory_rw);
|
||||
}
|
||||
|
||||
void module_enable_ro(const struct module *mod)
|
||||
void module_enable_ro(const struct module *mod, bool after_init)
|
||||
{
|
||||
frob_text(&mod->core_layout, set_memory_ro);
|
||||
frob_rodata(&mod->core_layout, set_memory_ro);
|
||||
frob_text(&mod->init_layout, set_memory_ro);
|
||||
frob_rodata(&mod->init_layout, set_memory_ro);
|
||||
|
||||
if (after_init)
|
||||
frob_ro_after_init(&mod->core_layout, set_memory_ro);
|
||||
}
|
||||
|
||||
static void module_enable_nx(const struct module *mod)
|
||||
{
|
||||
frob_rodata(&mod->core_layout, set_memory_nx);
|
||||
frob_ro_after_init(&mod->core_layout, set_memory_nx);
|
||||
frob_writable_data(&mod->core_layout, set_memory_nx);
|
||||
frob_rodata(&mod->init_layout, set_memory_nx);
|
||||
frob_writable_data(&mod->init_layout, set_memory_nx);
|
||||
|
@ -1923,6 +1938,7 @@ static void module_enable_nx(const struct module *mod)
|
|||
static void module_disable_nx(const struct module *mod)
|
||||
{
|
||||
frob_rodata(&mod->core_layout, set_memory_x);
|
||||
frob_ro_after_init(&mod->core_layout, set_memory_x);
|
||||
frob_writable_data(&mod->core_layout, set_memory_x);
|
||||
frob_rodata(&mod->init_layout, set_memory_x);
|
||||
frob_writable_data(&mod->init_layout, set_memory_x);
|
||||
|
@ -1965,6 +1981,8 @@ static void disable_ro_nx(const struct module_layout *layout)
|
|||
frob_text(layout, set_memory_rw);
|
||||
frob_rodata(layout, set_memory_rw);
|
||||
frob_rodata(layout, set_memory_x);
|
||||
frob_ro_after_init(layout, set_memory_rw);
|
||||
frob_ro_after_init(layout, set_memory_x);
|
||||
frob_writable_data(layout, set_memory_x);
|
||||
}
|
||||
|
||||
|
@ -2307,6 +2325,7 @@ static void layout_sections(struct module *mod, struct load_info *info)
|
|||
* finder in the two loops below */
|
||||
{ SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },
|
||||
{ SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },
|
||||
{ SHF_RO_AFTER_INIT | SHF_ALLOC, ARCH_SHF_SMALL },
|
||||
{ SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },
|
||||
{ ARCH_SHF_SMALL | SHF_ALLOC, 0 }
|
||||
};
|
||||
|
@ -2338,7 +2357,11 @@ static void layout_sections(struct module *mod, struct load_info *info)
|
|||
mod->core_layout.size = debug_align(mod->core_layout.size);
|
||||
mod->core_layout.ro_size = mod->core_layout.size;
|
||||
break;
|
||||
case 3: /* whole core */
|
||||
case 2: /* RO after init */
|
||||
mod->core_layout.size = debug_align(mod->core_layout.size);
|
||||
mod->core_layout.ro_after_init_size = mod->core_layout.size;
|
||||
break;
|
||||
case 4: /* whole core */
|
||||
mod->core_layout.size = debug_align(mod->core_layout.size);
|
||||
break;
|
||||
}
|
||||
|
@ -2368,7 +2391,14 @@ static void layout_sections(struct module *mod, struct load_info *info)
|
|||
mod->init_layout.size = debug_align(mod->init_layout.size);
|
||||
mod->init_layout.ro_size = mod->init_layout.size;
|
||||
break;
|
||||
case 3: /* whole init */
|
||||
case 2:
|
||||
/*
|
||||
* RO after init doesn't apply to init_layout (only
|
||||
* core_layout), so it just takes the value of ro_size.
|
||||
*/
|
||||
mod->init_layout.ro_after_init_size = mod->init_layout.ro_size;
|
||||
break;
|
||||
case 4: /* whole init */
|
||||
mod->init_layout.size = debug_align(mod->init_layout.size);
|
||||
break;
|
||||
}
|
||||
|
@ -2688,13 +2718,18 @@ static inline void kmemleak_load_module(const struct module *mod,
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_MODULE_SIG
|
||||
static int module_sig_check(struct load_info *info)
|
||||
static int module_sig_check(struct load_info *info, int flags)
|
||||
{
|
||||
int err = -ENOKEY;
|
||||
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
|
||||
const void *mod = info->hdr;
|
||||
|
||||
if (info->len > markerlen &&
|
||||
/*
|
||||
* Require flags == 0, as a module with version information
|
||||
* removed is no longer the module that was signed
|
||||
*/
|
||||
if (flags == 0 &&
|
||||
info->len > markerlen &&
|
||||
memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
|
||||
/* We truncate the module to discard the signature */
|
||||
info->len -= markerlen;
|
||||
|
@ -2713,7 +2748,7 @@ static int module_sig_check(struct load_info *info)
|
|||
return err;
|
||||
}
|
||||
#else /* !CONFIG_MODULE_SIG */
|
||||
static int module_sig_check(struct load_info *info)
|
||||
static int module_sig_check(struct load_info *info, int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -2921,8 +2956,12 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
|
|||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (!get_modinfo(info, "intree"))
|
||||
if (!get_modinfo(info, "intree")) {
|
||||
if (!test_taint(TAINT_OOT_MODULE))
|
||||
pr_warn("%s: loading out-of-tree module taints kernel.\n",
|
||||
mod->name);
|
||||
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
|
||||
}
|
||||
|
||||
if (get_modinfo(info, "staging")) {
|
||||
add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
|
||||
|
@ -3091,6 +3130,8 @@ static int move_module(struct module *mod, struct load_info *info)
|
|||
|
||||
static int check_module_license_and_versions(struct module *mod)
|
||||
{
|
||||
int prev_taint = test_taint(TAINT_PROPRIETARY_MODULE);
|
||||
|
||||
/*
|
||||
* ndiswrapper is under GPL by itself, but loads proprietary modules.
|
||||
* Don't use add_taint_module(), as it would prevent ndiswrapper from
|
||||
|
@ -3109,6 +3150,9 @@ static int check_module_license_and_versions(struct module *mod)
|
|||
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
|
||||
LOCKDEP_NOW_UNRELIABLE);
|
||||
|
||||
if (!prev_taint && test_taint(TAINT_PROPRIETARY_MODULE))
|
||||
pr_warn("%s: module license taints kernel.\n", mod->name);
|
||||
|
||||
#ifdef CONFIG_MODVERSIONS
|
||||
if ((mod->num_syms && !mod->crcs)
|
||||
|| (mod->num_gpl_syms && !mod->gpl_crcs)
|
||||
|
@ -3156,16 +3200,41 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* module_blacklist is a comma-separated list of module names */
|
||||
static char *module_blacklist;
|
||||
static bool blacklisted(char *module_name)
|
||||
{
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
if (!module_blacklist)
|
||||
return false;
|
||||
|
||||
for (p = module_blacklist; *p; p += len) {
|
||||
len = strcspn(p, ",");
|
||||
if (strlen(module_name) == len && !memcmp(module_name, p, len))
|
||||
return true;
|
||||
if (p[len] == ',')
|
||||
len++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
core_param(module_blacklist, module_blacklist, charp, 0400);
|
||||
|
||||
static struct module *layout_and_allocate(struct load_info *info, int flags)
|
||||
{
|
||||
/* Module within temporary copy. */
|
||||
struct module *mod;
|
||||
unsigned int ndx;
|
||||
int err;
|
||||
|
||||
mod = setup_load_info(info, flags);
|
||||
if (IS_ERR(mod))
|
||||
return mod;
|
||||
|
||||
if (blacklisted(mod->name))
|
||||
return ERR_PTR(-EPERM);
|
||||
|
||||
err = check_modinfo(mod, info, flags);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
@ -3179,6 +3248,15 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
|
|||
/* We will do a special allocation for per-cpu sections later. */
|
||||
info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
|
||||
|
||||
/*
|
||||
* Mark ro_after_init section with SHF_RO_AFTER_INIT so that
|
||||
* layout_sections() can put it in the right place.
|
||||
* Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set.
|
||||
*/
|
||||
ndx = find_sec(info, ".data..ro_after_init");
|
||||
if (ndx)
|
||||
info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
|
||||
|
||||
/* Determine total sizes, and put offsets in sh_entsize. For now
|
||||
this is done generically; there doesn't appear to be any
|
||||
special cases for the architectures. */
|
||||
|
@ -3345,12 +3423,14 @@ static noinline int do_init_module(struct module *mod)
|
|||
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
|
||||
rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
|
||||
#endif
|
||||
module_enable_ro(mod, true);
|
||||
mod_tree_remove_init(mod);
|
||||
disable_ro_nx(&mod->init_layout);
|
||||
module_arch_freeing_init(mod);
|
||||
mod->init_layout.base = NULL;
|
||||
mod->init_layout.size = 0;
|
||||
mod->init_layout.ro_size = 0;
|
||||
mod->init_layout.ro_after_init_size = 0;
|
||||
mod->init_layout.text_size = 0;
|
||||
/*
|
||||
* We want to free module_init, but be aware that kallsyms may be
|
||||
|
@ -3442,8 +3522,7 @@ 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);
|
||||
|
||||
/* Set RO and NX regions */
|
||||
module_enable_ro(mod);
|
||||
module_enable_ro(mod, false);
|
||||
module_enable_nx(mod);
|
||||
|
||||
/* Mark state as coming so strong_try_module_get() ignores us,
|
||||
|
@ -3499,7 +3578,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
|||
long err;
|
||||
char *after_dashes;
|
||||
|
||||
err = module_sig_check(info);
|
||||
err = module_sig_check(info, flags);
|
||||
if (err)
|
||||
goto free_copy;
|
||||
|
||||
|
|
Loading…
Reference in New Issue