|
@@ -313,8 +313,11 @@ struct load_info {
|
|
|
} index;
|
|
|
};
|
|
|
|
|
|
-/* We require a truly strong try_module_get(): 0 means failure due to
|
|
|
- ongoing or failed initialization etc. */
|
|
|
+/*
|
|
|
+ * We require a truly strong try_module_get(): 0 means success.
|
|
|
+ * Otherwise an error is returned due to ongoing or failed
|
|
|
+ * initialization etc.
|
|
|
+ */
|
|
|
static inline int strong_try_module_get(struct module *mod)
|
|
|
{
|
|
|
BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
|
|
@@ -330,7 +333,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
|
|
|
enum lockdep_ok lockdep_ok)
|
|
|
{
|
|
|
add_taint(flag, lockdep_ok);
|
|
|
- mod->taints |= (1U << flag);
|
|
|
+ set_bit(flag, &mod->taints);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1138,24 +1141,13 @@ static inline int module_unload_init(struct module *mod)
|
|
|
static size_t module_flags_taint(struct module *mod, char *buf)
|
|
|
{
|
|
|
size_t l = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
|
|
|
+ if (taint_flags[i].module && test_bit(i, &mod->taints))
|
|
|
+ buf[l++] = taint_flags[i].true;
|
|
|
+ }
|
|
|
|
|
|
- if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
|
|
|
- buf[l++] = 'P';
|
|
|
- if (mod->taints & (1 << TAINT_OOT_MODULE))
|
|
|
- buf[l++] = 'O';
|
|
|
- if (mod->taints & (1 << TAINT_FORCED_MODULE))
|
|
|
- buf[l++] = 'F';
|
|
|
- if (mod->taints & (1 << TAINT_CRAP))
|
|
|
- buf[l++] = 'C';
|
|
|
- if (mod->taints & (1 << TAINT_UNSIGNED_MODULE))
|
|
|
- buf[l++] = 'E';
|
|
|
- if (mod->taints & (1 << TAINT_LIVEPATCH))
|
|
|
- buf[l++] = 'K';
|
|
|
- /*
|
|
|
- * TAINT_FORCED_RMMOD: could be added.
|
|
|
- * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
|
|
|
- * apply to modules.
|
|
|
- */
|
|
|
return l;
|
|
|
}
|
|
|
|
|
@@ -1911,6 +1903,9 @@ static void frob_writable_data(const struct module_layout *layout,
|
|
|
/* livepatching wants to disable read-only so it can frob module. */
|
|
|
void module_disable_ro(const struct module *mod)
|
|
|
{
|
|
|
+ if (!rodata_enabled)
|
|
|
+ return;
|
|
|
+
|
|
|
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);
|
|
@@ -1920,6 +1915,9 @@ void module_disable_ro(const struct module *mod)
|
|
|
|
|
|
void module_enable_ro(const struct module *mod, bool after_init)
|
|
|
{
|
|
|
+ if (!rodata_enabled)
|
|
|
+ return;
|
|
|
+
|
|
|
frob_text(&mod->core_layout, set_memory_ro);
|
|
|
frob_rodata(&mod->core_layout, set_memory_ro);
|
|
|
frob_text(&mod->init_layout, set_memory_ro);
|
|
@@ -1952,6 +1950,9 @@ void set_all_modules_text_rw(void)
|
|
|
{
|
|
|
struct module *mod;
|
|
|
|
|
|
+ if (!rodata_enabled)
|
|
|
+ return;
|
|
|
+
|
|
|
mutex_lock(&module_mutex);
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
@@ -1968,9 +1969,18 @@ void set_all_modules_text_ro(void)
|
|
|
{
|
|
|
struct module *mod;
|
|
|
|
|
|
+ if (!rodata_enabled)
|
|
|
+ return;
|
|
|
+
|
|
|
mutex_lock(&module_mutex);
|
|
|
list_for_each_entry_rcu(mod, &modules, list) {
|
|
|
- if (mod->state == MODULE_STATE_UNFORMED)
|
|
|
+ /*
|
|
|
+ * Ignore going modules since it's possible that ro
|
|
|
+ * protection has already been disabled, otherwise we'll
|
|
|
+ * run into protection faults at module deallocation.
|
|
|
+ */
|
|
|
+ if (mod->state == MODULE_STATE_UNFORMED ||
|
|
|
+ mod->state == MODULE_STATE_GOING)
|
|
|
continue;
|
|
|
|
|
|
frob_text(&mod->core_layout, set_memory_ro);
|
|
@@ -1981,10 +1991,12 @@ void set_all_modules_text_ro(void)
|
|
|
|
|
|
static void disable_ro_nx(const struct module_layout *layout)
|
|
|
{
|
|
|
- frob_text(layout, set_memory_rw);
|
|
|
- frob_rodata(layout, set_memory_rw);
|
|
|
+ if (rodata_enabled) {
|
|
|
+ frob_text(layout, set_memory_rw);
|
|
|
+ frob_rodata(layout, set_memory_rw);
|
|
|
+ frob_ro_after_init(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);
|
|
|
}
|
|
@@ -3709,6 +3721,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
|
|
sysfs_cleanup:
|
|
|
mod_sysfs_teardown(mod);
|
|
|
coming_cleanup:
|
|
|
+ mod->state = MODULE_STATE_GOING;
|
|
|
blocking_notifier_call_chain(&module_notify_list,
|
|
|
MODULE_STATE_GOING, mod);
|
|
|
klp_module_going(mod);
|
|
@@ -4042,6 +4055,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
|
|
}
|
|
|
#endif /* CONFIG_KALLSYMS */
|
|
|
|
|
|
+/* Maximum number of characters written by module_flags() */
|
|
|
+#define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)
|
|
|
+
|
|
|
+/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
|
|
|
static char *module_flags(struct module *mod, char *buf)
|
|
|
{
|
|
|
int bx = 0;
|
|
@@ -4086,7 +4103,7 @@ static void m_stop(struct seq_file *m, void *p)
|
|
|
static int m_show(struct seq_file *m, void *p)
|
|
|
{
|
|
|
struct module *mod = list_entry(p, struct module, list);
|
|
|
- char buf[8];
|
|
|
+ char buf[MODULE_FLAGS_BUF_SIZE];
|
|
|
|
|
|
/* We always ignore unformed modules. */
|
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
@@ -4257,7 +4274,7 @@ EXPORT_SYMBOL_GPL(__module_text_address);
|
|
|
void print_modules(void)
|
|
|
{
|
|
|
struct module *mod;
|
|
|
- char buf[8];
|
|
|
+ char buf[MODULE_FLAGS_BUF_SIZE];
|
|
|
|
|
|
printk(KERN_DEFAULT "Modules linked in:");
|
|
|
/* Most callers should already have preempt disabled, but make sure */
|