futex: Do not apply time namespace adjustment on FUTEX_LOCK_PI
[linux-2.6-microblaze.git] / kernel / module.c
index 3047935..20fb004 100644 (file)
@@ -2146,6 +2146,8 @@ void __weak module_arch_freeing_init(struct module *mod)
 {
 }
 
+static void cfi_cleanup(struct module *mod);
+
 /* Free a module, remove from lists, etc. */
 static void free_module(struct module *mod)
 {
@@ -2187,6 +2189,9 @@ static void free_module(struct module *mod)
        synchronize_rcu();
        mutex_unlock(&module_mutex);
 
+       /* Clean up CFI for the module. */
+       cfi_cleanup(mod);
+
        /* This may be empty, but that's OK */
        module_arch_freeing_init(mod);
        module_memfree(mod->init_layout.base);
@@ -3866,6 +3871,8 @@ static int unknown_module_param_cb(char *param, char *val, const char *modname,
        return 0;
 }
 
+static void cfi_init(struct module *mod);
+
 /*
  * Allocate and load the module: note that size of section 0 is always
  * zero, and we rely on this for optional sections.
@@ -3997,6 +4004,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        flush_module_icache(mod);
 
+       /* Setup CFI for the module. */
+       cfi_init(mod);
+
        /* Now copy in args */
        mod->args = strndup_user(uargs, ~0UL >> 1);
        if (IS_ERR(mod->args)) {
@@ -4070,6 +4080,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
        synchronize_rcu();
        kfree(mod->args);
  free_arch_cleanup:
+       cfi_cleanup(mod);
        module_arch_cleanup(mod);
  free_modinfo:
        free_modinfo(mod);
@@ -4415,6 +4426,38 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
 #endif /* CONFIG_LIVEPATCH */
 #endif /* CONFIG_KALLSYMS */
 
+static void cfi_init(struct module *mod)
+{
+#ifdef CONFIG_CFI_CLANG
+       initcall_t *init;
+       exitcall_t *exit;
+
+       rcu_read_lock_sched();
+       mod->cfi_check = (cfi_check_fn)
+               find_kallsyms_symbol_value(mod, "__cfi_check");
+       init = (initcall_t *)
+               find_kallsyms_symbol_value(mod, "__cfi_jt_init_module");
+       exit = (exitcall_t *)
+               find_kallsyms_symbol_value(mod, "__cfi_jt_cleanup_module");
+       rcu_read_unlock_sched();
+
+       /* Fix init/exit functions to point to the CFI jump table */
+       if (init)
+               mod->init = *init;
+       if (exit)
+               mod->exit = *exit;
+
+       cfi_module_add(mod, module_addr_min);
+#endif
+}
+
+static void cfi_cleanup(struct module *mod)
+{
+#ifdef CONFIG_CFI_CLANG
+       cfi_module_remove(mod, module_addr_min);
+#endif
+}
+
 /* Maximum number of characters written by module_flags() */
 #define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4)