diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 4810 |
1 files changed, 0 insertions, 4810 deletions
diff --git a/kernel/module.c b/kernel/module.c deleted file mode 100644 index 6cea788fd965..000000000000 --- a/kernel/module.c +++ /dev/null @@ -1,4810 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2002 Richard Henderson - * Copyright (C) 2001 Rusty Russell, 2002, 2010 Rusty Russell IBM. - */ - -#define INCLUDE_VERMAGIC - -#include <linux/export.h> -#include <linux/extable.h> -#include <linux/moduleloader.h> -#include <linux/module_signature.h> -#include <linux/trace_events.h> -#include <linux/init.h> -#include <linux/kallsyms.h> -#include <linux/buildid.h> -#include <linux/file.h> -#include <linux/fs.h> -#include <linux/sysfs.h> -#include <linux/kernel.h> -#include <linux/kernel_read_file.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/elf.h> -#include <linux/proc_fs.h> -#include <linux/security.h> -#include <linux/seq_file.h> -#include <linux/syscalls.h> -#include <linux/fcntl.h> -#include <linux/rcupdate.h> -#include <linux/capability.h> -#include <linux/cpu.h> -#include <linux/moduleparam.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/vermagic.h> -#include <linux/notifier.h> -#include <linux/sched.h> -#include <linux/device.h> -#include <linux/string.h> -#include <linux/mutex.h> -#include <linux/rculist.h> -#include <linux/uaccess.h> -#include <asm/cacheflush.h> -#include <linux/set_memory.h> -#include <asm/mmu_context.h> -#include <linux/license.h> -#include <asm/sections.h> -#include <linux/tracepoint.h> -#include <linux/ftrace.h> -#include <linux/livepatch.h> -#include <linux/async.h> -#include <linux/percpu.h> -#include <linux/kmemleak.h> -#include <linux/jump_label.h> -#include <linux/pfn.h> -#include <linux/bsearch.h> -#include <linux/dynamic_debug.h> -#include <linux/audit.h> -#include <uapi/linux/module.h> -#include "module-internal.h" - -#define CREATE_TRACE_POINTS -#include <trace/events/module.h> - -#ifndef ARCH_SHF_SMALL -#define ARCH_SHF_SMALL 0 -#endif - -/* - * Modules' sections will be aligned on page boundaries - * to ensure complete separation of code and data, but - * only when CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y - */ -#ifdef CONFIG_ARCH_HAS_STRICT_MODULE_RWX -# define debug_align(X) ALIGN(X, PAGE_SIZE) -#else -# define debug_align(X) (X) -#endif - -/* If this is set, the section belongs in the init part of the module */ -#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) - -/* - * Mutex protects: - * 1) List of modules (also safely readable with preempt_disable), - * 2) module_use links, - * 3) module_addr_min/module_addr_max. - * (delete and add uses RCU list operations). - */ -static DEFINE_MUTEX(module_mutex); -static LIST_HEAD(modules); - -/* Work queue for freeing init sections in success case */ -static void do_free_init(struct work_struct *w); -static DECLARE_WORK(init_free_wq, do_free_init); -static LLIST_HEAD(init_free_list); - -#ifdef CONFIG_MODULES_TREE_LOOKUP - -/* - * Use a latched RB-tree for __module_address(); this allows us to use - * RCU-sched lookups of the address from any context. - * - * This is conditional on PERF_EVENTS || TRACING because those can really hit - * __module_address() hard by doing a lot of stack unwinding; potentially from - * NMI context. - */ - -static __always_inline unsigned long __mod_tree_val(struct latch_tree_node *n) -{ - struct module_layout *layout = container_of(n, struct module_layout, mtn.node); - - return (unsigned long)layout->base; -} - -static __always_inline unsigned long __mod_tree_size(struct latch_tree_node *n) -{ - struct module_layout *layout = container_of(n, struct module_layout, mtn.node); - - return (unsigned long)layout->size; -} - -static __always_inline bool -mod_tree_less(struct latch_tree_node *a, struct latch_tree_node *b) -{ - return __mod_tree_val(a) < __mod_tree_val(b); -} - -static __always_inline int -mod_tree_comp(void *key, struct latch_tree_node *n) -{ - unsigned long val = (unsigned long)key; - unsigned long start, end; - - start = __mod_tree_val(n); - if (val < start) - return -1; - - end = start + __mod_tree_size(n); - if (val >= end) - return 1; - - return 0; -} - -static const struct latch_tree_ops mod_tree_ops = { - .less = mod_tree_less, - .comp = mod_tree_comp, -}; - -static struct mod_tree_root { - struct latch_tree_root root; - unsigned long addr_min; - unsigned long addr_max; -} mod_tree __cacheline_aligned = { - .addr_min = -1UL, -}; - -#define module_addr_min mod_tree.addr_min -#define module_addr_max mod_tree.addr_max - -static noinline void __mod_tree_insert(struct mod_tree_node *node) -{ - latch_tree_insert(&node->node, &mod_tree.root, &mod_tree_ops); -} - -static void __mod_tree_remove(struct mod_tree_node *node) -{ - latch_tree_erase(&node->node, &mod_tree.root, &mod_tree_ops); -} - -/* - * These modifications: insert, remove_init and remove; are serialized by the - * module_mutex. - */ -static void mod_tree_insert(struct module *mod) -{ - mod->core_layout.mtn.mod = mod; - mod->init_layout.mtn.mod = mod; - - __mod_tree_insert(&mod->core_layout.mtn); - if (mod->init_layout.size) - __mod_tree_insert(&mod->init_layout.mtn); -} - -static void mod_tree_remove_init(struct module *mod) -{ - if (mod->init_layout.size) - __mod_tree_remove(&mod->init_layout.mtn); -} - -static void mod_tree_remove(struct module *mod) -{ - __mod_tree_remove(&mod->core_layout.mtn); - mod_tree_remove_init(mod); -} - -static struct module *mod_find(unsigned long addr) -{ - struct latch_tree_node *ltn; - - ltn = latch_tree_find((void *)addr, &mod_tree.root, &mod_tree_ops); - if (!ltn) - return NULL; - - return container_of(ltn, struct mod_tree_node, node)->mod; -} - -#else /* MODULES_TREE_LOOKUP */ - -static unsigned long module_addr_min = -1UL, module_addr_max = 0; - -static void mod_tree_insert(struct module *mod) { } -static void mod_tree_remove_init(struct module *mod) { } -static void mod_tree_remove(struct module *mod) { } - -static struct module *mod_find(unsigned long addr) -{ - struct module *mod; - - list_for_each_entry_rcu(mod, &modules, list, - lockdep_is_held(&module_mutex)) { - if (within_module(addr, mod)) - return mod; - } - - return NULL; -} - -#endif /* MODULES_TREE_LOOKUP */ - -/* - * Bounds of module text, for speeding up __module_address. - * Protected by module_mutex. - */ -static void __mod_update_bounds(void *base, unsigned int size) -{ - unsigned long min = (unsigned long)base; - unsigned long max = min + size; - - if (min < module_addr_min) - module_addr_min = min; - if (max > module_addr_max) - module_addr_max = max; -} - -static void mod_update_bounds(struct module *mod) -{ - __mod_update_bounds(mod->core_layout.base, mod->core_layout.size); - if (mod->init_layout.size) - __mod_update_bounds(mod->init_layout.base, mod->init_layout.size); -} - -#ifdef CONFIG_KGDB_KDB -struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ -#endif /* CONFIG_KGDB_KDB */ - -static void module_assert_mutex_or_preempt(void) -{ -#ifdef CONFIG_LOCKDEP - if (unlikely(!debug_locks)) - return; - - WARN_ON_ONCE(!rcu_read_lock_sched_held() && - !lockdep_is_held(&module_mutex)); -#endif -} - -#ifdef CONFIG_MODULE_SIG -static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); -module_param(sig_enforce, bool_enable_only, 0644); - -void set_module_sig_enforced(void) -{ - sig_enforce = true; -} -#else -#define sig_enforce false -#endif - -/* - * Export sig_enforce kernel cmdline parameter to allow other subsystems rely - * on that instead of directly to CONFIG_MODULE_SIG_FORCE config. - */ -bool is_module_sig_enforced(void) -{ - return sig_enforce; -} -EXPORT_SYMBOL(is_module_sig_enforced); - -/* Block module loading/unloading? */ -int modules_disabled = 0; -core_param(nomodule, modules_disabled, bint, 0); - -/* Waiting for a module to finish initializing? */ -static DECLARE_WAIT_QUEUE_HEAD(module_wq); - -static BLOCKING_NOTIFIER_HEAD(module_notify_list); - -int register_module_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&module_notify_list, nb); -} -EXPORT_SYMBOL(register_module_notifier); - -int unregister_module_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&module_notify_list, nb); -} -EXPORT_SYMBOL(unregister_module_notifier); - -/* - * 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); - if (mod && mod->state == MODULE_STATE_COMING) - return -EBUSY; - if (try_module_get(mod)) - return 0; - else - return -ENOENT; -} - -static inline void add_taint_module(struct module *mod, unsigned flag, - enum lockdep_ok lockdep_ok) -{ - add_taint(flag, lockdep_ok); - set_bit(flag, &mod->taints); -} - -/* - * A thread that wants to hold a reference to a module only while it - * is running can call this to safely exit. - */ -void __noreturn __module_put_and_kthread_exit(struct module *mod, long code) -{ - module_put(mod); - kthread_exit(code); -} -EXPORT_SYMBOL(__module_put_and_kthread_exit); - -/* Find a module section: 0 means not found. */ -static unsigned int find_sec(const struct load_info *info, const char *name) -{ - unsigned int i; - - for (i = 1; i < info->hdr->e_shnum; i++) { - Elf_Shdr *shdr = &info->sechdrs[i]; - /* Alloc bit cleared means "ignore it." */ - if ((shdr->sh_flags & SHF_ALLOC) - && strcmp(info->secstrings + shdr->sh_name, name) == 0) - return i; - } - return 0; -} - -/* Find a module section, or NULL. */ -static void *section_addr(const struct load_info *info, const char *name) -{ - /* Section 0 has sh_addr 0. */ - return (void *)info->sechdrs[find_sec(info, name)].sh_addr; -} - -/* Find a module section, or NULL. Fill in number of "objects" in section. */ -static void *section_objs(const struct load_info *info, - const char *name, - size_t object_size, - unsigned int *num) -{ - unsigned int sec = find_sec(info, name); - - /* Section 0 has sh_addr 0 and sh_size 0. */ - *num = info->sechdrs[sec].sh_size / object_size; - return (void *)info->sechdrs[sec].sh_addr; -} - -/* Find a module section: 0 means not found. Ignores SHF_ALLOC flag. */ -static unsigned int find_any_sec(const struct load_info *info, const char *name) -{ - unsigned int i; - - for (i = 1; i < info->hdr->e_shnum; i++) { - Elf_Shdr *shdr = &info->sechdrs[i]; - if (strcmp(info->secstrings + shdr->sh_name, name) == 0) - return i; - } - return 0; -} - -/* - * Find a module section, or NULL. Fill in number of "objects" in section. - * Ignores SHF_ALLOC flag. - */ -static __maybe_unused void *any_section_objs(const struct load_info *info, - const char *name, - size_t object_size, - unsigned int *num) -{ - unsigned int sec = find_any_sec(info, name); - - /* Section 0 has sh_addr 0 and sh_size 0. */ - *num = info->sechdrs[sec].sh_size / object_size; - return (void *)info->sechdrs[sec].sh_addr; -} - -/* Provided by the linker */ -extern const struct kernel_symbol __start___ksymtab[]; -extern const struct kernel_symbol __stop___ksymtab[]; -extern const struct kernel_symbol __start___ksymtab_gpl[]; -extern const struct kernel_symbol __stop___ksymtab_gpl[]; -extern const s32 __start___kcrctab[]; -extern const s32 __start___kcrctab_gpl[]; - -#ifndef CONFIG_MODVERSIONS -#define symversion(base, idx) NULL -#else -#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) -#endif - -struct symsearch { - const struct kernel_symbol *start, *stop; - const s32 *crcs; - enum mod_license { - NOT_GPL_ONLY, - GPL_ONLY, - } license; -}; - -struct find_symbol_arg { - /* Input */ - const char *name; - bool gplok; - bool warn; - - /* Output */ - struct module *owner; - const s32 *crc; - const struct kernel_symbol *sym; - enum mod_license license; -}; - -static bool check_exported_symbol(const struct symsearch *syms, - struct module *owner, - unsigned int symnum, void *data) -{ - struct find_symbol_arg *fsa = data; - - if (!fsa->gplok && syms->license == GPL_ONLY) - return false; - fsa->owner = owner; - fsa->crc = symversion(syms->crcs, symnum); - fsa->sym = &syms->start[symnum]; - fsa->license = syms->license; - return true; -} - -static unsigned long kernel_symbol_value(const struct kernel_symbol *sym) -{ -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - return (unsigned long)offset_to_ptr(&sym->value_offset); -#else - return sym->value; -#endif -} - -static const char *kernel_symbol_name(const struct kernel_symbol *sym) -{ -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - return offset_to_ptr(&sym->name_offset); -#else - return sym->name; -#endif -} - -static const char *kernel_symbol_namespace(const struct kernel_symbol *sym) -{ -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - if (!sym->namespace_offset) - return NULL; - return offset_to_ptr(&sym->namespace_offset); -#else - return sym->namespace; -#endif -} - -static int cmp_name(const void *name, const void *sym) -{ - return strcmp(name, kernel_symbol_name(sym)); -} - -static bool find_exported_symbol_in_section(const struct symsearch *syms, - struct module *owner, - void *data) -{ - struct find_symbol_arg *fsa = data; - struct kernel_symbol *sym; - - sym = bsearch(fsa->name, syms->start, syms->stop - syms->start, - sizeof(struct kernel_symbol), cmp_name); - - if (sym != NULL && check_exported_symbol(syms, owner, - sym - syms->start, data)) - return true; - - return false; -} - -/* - * Find an exported symbol and return it, along with, (optional) crc and - * (optional) module which owns it. Needs preempt disabled or module_mutex. - */ -static bool find_symbol(struct find_symbol_arg *fsa) -{ - static const struct symsearch arr[] = { - { __start___ksymtab, __stop___ksymtab, __start___kcrctab, - NOT_GPL_ONLY }, - { __start___ksymtab_gpl, __stop___ksymtab_gpl, - __start___kcrctab_gpl, - GPL_ONLY }, - }; - struct module *mod; - unsigned int i; - - module_assert_mutex_or_preempt(); - - for (i = 0; i < ARRAY_SIZE(arr); i++) - if (find_exported_symbol_in_section(&arr[i], NULL, fsa)) - return true; - - list_for_each_entry_rcu(mod, &modules, list, - lockdep_is_held(&module_mutex)) { - struct symsearch arr[] = { - { mod->syms, mod->syms + mod->num_syms, mod->crcs, - NOT_GPL_ONLY }, - { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms, - mod->gpl_crcs, - GPL_ONLY }, - }; - - if (mod->state == MODULE_STATE_UNFORMED) - continue; - - for (i = 0; i < ARRAY_SIZE(arr); i++) - if (find_exported_symbol_in_section(&arr[i], mod, fsa)) - return true; - } - - pr_debug("Failed to find symbol %s\n", fsa->name); - return false; -} - -/* - * Search for module by name: must hold module_mutex (or preempt disabled - * for read-only access). - */ -static struct module *find_module_all(const char *name, size_t len, - bool even_unformed) -{ - struct module *mod; - - module_assert_mutex_or_preempt(); - - list_for_each_entry_rcu(mod, &modules, list, - lockdep_is_held(&module_mutex)) { - if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) - continue; - if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) - return mod; - } - return NULL; -} - -struct module *find_module(const char *name) -{ - return find_module_all(name, strlen(name), false); -} - -#ifdef CONFIG_SMP - -static inline void __percpu *mod_percpu(struct module *mod) -{ - return mod->percpu; -} - -static int percpu_modalloc(struct module *mod, struct load_info *info) -{ - Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; - unsigned long align = pcpusec->sh_addralign; - - if (!pcpusec->sh_size) - return 0; - - if (align > PAGE_SIZE) { - pr_warn("%s: per-cpu alignment %li > %li\n", - mod->name, align, PAGE_SIZE); - align = PAGE_SIZE; - } - - mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align); - if (!mod->percpu) { - pr_warn("%s: Could not allocate %lu bytes percpu data\n", - mod->name, (unsigned long)pcpusec->sh_size); - return -ENOMEM; - } - mod->percpu_size = pcpusec->sh_size; - return 0; -} - -static void percpu_modfree(struct module *mod) -{ - free_percpu(mod->percpu); -} - -static unsigned int find_pcpusec(struct load_info *info) -{ - return find_sec(info, ".data..percpu"); -} - -static void percpu_modcopy(struct module *mod, - const void *from, unsigned long size) -{ - int cpu; - - for_each_possible_cpu(cpu) - memcpy(per_cpu_ptr(mod->percpu, cpu), from, size); -} - -bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr) -{ - struct module *mod; - unsigned int cpu; - - preempt_disable(); - - list_for_each_entry_rcu(mod, &modules, list) { - if (mod->state == MODULE_STATE_UNFORMED) - continue; - if (!mod->percpu_size) - continue; - for_each_possible_cpu(cpu) { - void *start = per_cpu_ptr(mod->percpu, cpu); - void *va = (void *)addr; - - if (va >= start && va < start + mod->percpu_size) { - if (can_addr) { - *can_addr = (unsigned long) (va - start); - *can_addr += (unsigned long) - per_cpu_ptr(mod->percpu, - get_boot_cpu_id()); - } - preempt_enable(); - return true; - } - } - } - - preempt_enable(); - return false; -} - -/** - * is_module_percpu_address() - test whether address is from module static percpu - * @addr: address to test - * - * Test whether @addr belongs to module static percpu area. - * - * Return: %true if @addr is from module static percpu area - */ -bool is_module_percpu_address(unsigned long addr) -{ - return __is_module_percpu_address(addr, NULL); -} - -#else /* ... !CONFIG_SMP */ - -static inline void __percpu *mod_percpu(struct module *mod) -{ - return NULL; -} -static int percpu_modalloc(struct module *mod, struct load_info *info) -{ - /* UP modules shouldn't have this section: ENOMEM isn't quite right */ - if (info->sechdrs[info->index.pcpu].sh_size != 0) - return -ENOMEM; - return 0; -} -static inline void percpu_modfree(struct module *mod) -{ -} -static unsigned int find_pcpusec(struct load_info *info) -{ - return 0; -} -static inline void percpu_modcopy(struct module *mod, - const void *from, unsigned long size) -{ - /* pcpusec should be 0, and size of that section should be 0. */ - BUG_ON(size != 0); -} -bool is_module_percpu_address(unsigned long addr) -{ - return false; -} - -bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr) -{ - return false; -} - -#endif /* CONFIG_SMP */ - -#define MODINFO_ATTR(field) \ -static void setup_modinfo_##field(struct module *mod, const char *s) \ -{ \ - mod->field = kstrdup(s, GFP_KERNEL); \ -} \ -static ssize_t show_modinfo_##field(struct module_attribute *mattr, \ - struct module_kobject *mk, char *buffer) \ -{ \ - return scnprintf(buffer, PAGE_SIZE, "%s\n", mk->mod->field); \ -} \ -static int modinfo_##field##_exists(struct module *mod) \ -{ \ - return mod->field != NULL; \ -} \ -static void free_modinfo_##field(struct module *mod) \ -{ \ - kfree(mod->field); \ - mod->field = NULL; \ -} \ -static struct module_attribute modinfo_##field = { \ - .attr = { .name = __stringify(field), .mode = 0444 }, \ - .show = show_modinfo_##field, \ - .setup = setup_modinfo_##field, \ - .test = modinfo_##field##_exists, \ - .free = free_modinfo_##field, \ -}; - -MODINFO_ATTR(version); -MODINFO_ATTR(srcversion); - -static char last_unloaded_module[MODULE_NAME_LEN+1]; - -#ifdef CONFIG_MODULE_UNLOAD - -EXPORT_TRACEPOINT_SYMBOL(module_get); - -/* MODULE_REF_BASE is the base reference count by kmodule loader. */ -#define MODULE_REF_BASE 1 - -/* Init the unload section of the module. */ -static int module_unload_init(struct module *mod) -{ - /* - * Initialize reference counter to MODULE_REF_BASE. - * refcnt == 0 means module is going. - */ - atomic_set(&mod->refcnt, MODULE_REF_BASE); - - INIT_LIST_HEAD(&mod->source_list); - INIT_LIST_HEAD(&mod->target_list); - - /* Hold reference count during initialization. */ - atomic_inc(&mod->refcnt); - - return 0; -} - -/* Does a already use b? */ -static int already_uses(struct module *a, struct module *b) -{ - struct module_use *use; - - list_for_each_entry(use, &b->source_list, source_list) { - if (use->source == a) { - pr_debug("%s uses %s!\n", a->name, b->name); - return 1; - } - } - pr_debug("%s does not use %s!\n", a->name, b->name); - return 0; -} - -/* - * Module a uses b - * - we add 'a' as a "source", 'b' as a "target" of module use - * - the module_use is added to the list of 'b' sources (so - * 'b' can walk the list to see who sourced them), and of 'a' - * targets (so 'a' can see what modules it targets). - */ -static int add_module_usage(struct module *a, struct module *b) -{ - struct module_use *use; - - pr_debug("Allocating new usage for %s.\n", a->name); - use = kmalloc(sizeof(*use), GFP_ATOMIC); - if (!use) - return -ENOMEM; - - use->source = a; - use->target = b; - list_add(&use->source_list, &b->source_list); - list_add(&use->target_list, &a->target_list); - return 0; -} - -/* Module a uses b: caller needs module_mutex() */ -static int ref_module(struct module *a, struct module *b) -{ - int err; - - if (b == NULL || already_uses(a, b)) - return 0; - - /* If module isn't available, we fail. */ - err = strong_try_module_get(b); - if (err) - return err; - - err = add_module_usage(a, b); - if (err) { - module_put(b); - return err; - } - return 0; -} - -/* Clear the unload stuff of the module. */ -static void module_unload_free(struct module *mod) -{ - struct module_use *use, *tmp; - - mutex_lock(&module_mutex); - list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) { - struct module *i = use->target; - pr_debug("%s unusing %s\n", mod->name, i->name); - module_put(i); - list_del(&use->source_list); - list_del(&use->target_list); - kfree(use); - } - mutex_unlock(&module_mutex); -} - -#ifdef CONFIG_MODULE_FORCE_UNLOAD -static inline int try_force_unload(unsigned int flags) -{ - int ret = (flags & O_TRUNC); - if (ret) - add_taint(TAINT_FORCED_RMMOD, LOCKDEP_NOW_UNRELIABLE); - return ret; -} -#else -static inline int try_force_unload(unsigned int flags) -{ - return 0; -} -#endif /* CONFIG_MODULE_FORCE_UNLOAD */ - -/* Try to release refcount of module, 0 means success. */ -static int try_release_module_ref(struct module *mod) -{ - int ret; - - /* Try to decrement refcnt which we set at loading */ - ret = atomic_sub_return(MODULE_REF_BASE, &mod->refcnt); - BUG_ON(ret < 0); - if (ret) - /* Someone can put this right now, recover with checking */ - ret = atomic_add_unless(&mod->refcnt, MODULE_REF_BASE, 0); - - return ret; -} - -static int try_stop_module(struct module *mod, int flags, int *forced) -{ - /* If it's not unused, quit unless we're forcing. */ - if (try_release_module_ref(mod) != 0) { - *forced = try_force_unload(flags); - if (!(*forced)) - return -EWOULDBLOCK; - } - - /* Mark it as dying. */ - mod->state = MODULE_STATE_GOING; - - return 0; -} - -/** - * module_refcount() - return the refcount or -1 if unloading - * @mod: the module we're checking - * - * Return: - * -1 if the module is in the process of unloading - * otherwise the number of references in the kernel to the module - */ -int module_refcount(struct module *mod) -{ - return atomic_read(&mod->refcnt) - MODULE_REF_BASE; -} -EXPORT_SYMBOL(module_refcount); - -/* This exists whether we can unload or not */ -static void free_module(struct module *mod); - -SYSCALL_DEFINE2(delete_module, const char __user *, name_user, - unsigned int, flags) -{ - struct module *mod; - char name[MODULE_NAME_LEN]; - int ret, forced = 0; - - if (!capable(CAP_SYS_MODULE) || modules_disabled) - return -EPERM; - - if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) - return -EFAULT; - name[MODULE_NAME_LEN-1] = '\0'; - - audit_log_kern_module(name); - - if (mutex_lock_interruptible(&module_mutex) != 0) - return -EINTR; - - mod = find_module(name); - if (!mod) { - ret = -ENOENT; - goto out; - } - - if (!list_empty(&mod->source_list)) { - /* Other modules depend on us: get rid of them first. */ - ret = -EWOULDBLOCK; - goto out; - } - - /* Doing init or already dying? */ - if (mod->state != MODULE_STATE_LIVE) { - /* FIXME: if (force), slam module count damn the torpedoes */ - pr_debug("%s already dying\n", mod->name); - ret = -EBUSY; - goto out; - } - - /* If it has an init func, it must have an exit func to unload */ - if (mod->init && !mod->exit) { - forced = try_force_unload(flags); - if (!forced) { - /* This module can't be removed */ - ret = -EBUSY; - goto out; - } - } - - ret = try_stop_module(mod, flags, &forced); - if (ret != 0) - goto out; - - mutex_unlock(&module_mutex); - /* Final destruction now no one is using it. */ - if (mod->exit != NULL) - mod->exit(); - blocking_notifier_call_chain(&module_notify_list, - MODULE_STATE_GOING, mod); - klp_module_going(mod); - ftrace_release_mod(mod); - - async_synchronize_full(); - - /* Store the name of the last unloaded module for diagnostic purposes */ - strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); - - free_module(mod); - /* someone could wait for the module in add_unformed_module() */ - wake_up_all(&module_wq); - return 0; -out: - mutex_unlock(&module_mutex); - return ret; -} - -static inline void print_unload_info(struct seq_file *m, struct module *mod) -{ - struct module_use *use; - int printed_something = 0; - - seq_printf(m, " %i ", module_refcount(mod)); - - /* - * Always include a trailing , so userspace can differentiate - * between this and the old multi-field proc format. - */ - list_for_each_entry(use, &mod->source_list, source_list) { - printed_something = 1; - seq_printf(m, "%s,", use->source->name); - } - - if (mod->init != NULL && mod->exit == NULL) { - printed_something = 1; - seq_puts(m, "[permanent],"); - } - - if (!printed_something) - seq_puts(m, "-"); -} - -void __symbol_put(const char *symbol) -{ - struct find_symbol_arg fsa = { - .name = symbol, - .gplok = true, - }; - - preempt_disable(); - BUG_ON(!find_symbol(&fsa)); - module_put(fsa.owner); - preempt_enable(); -} -EXPORT_SYMBOL(__symbol_put); - -/* Note this assumes addr is a function, which it currently always is. */ -void symbol_put_addr(void *addr) -{ - struct module *modaddr; - unsigned long a = (unsigned long)dereference_function_descriptor(addr); - - if (core_kernel_text(a)) - return; - - /* - * Even though we hold a reference on the module; we still need to - * disable preemption in order to safely traverse the data structure. - */ - preempt_disable(); - modaddr = __module_text_address(a); - BUG_ON(!modaddr); - module_put(modaddr); - preempt_enable(); -} -EXPORT_SYMBOL_GPL(symbol_put_addr); - -static ssize_t show_refcnt(struct module_attribute *mattr, - struct module_kobject *mk, char *buffer) -{ - return sprintf(buffer, "%i\n", module_refcount(mk->mod)); -} - -static struct module_attribute modinfo_refcnt = - __ATTR(refcnt, 0444, show_refcnt, NULL); - -void __module_get(struct module *module) -{ - if (module) { - preempt_disable(); - atomic_inc(&module->refcnt); - trace_module_get(module, _RET_IP_); - preempt_enable(); - } -} -EXPORT_SYMBOL(__module_get); - -bool try_module_get(struct module *module) -{ - bool ret = true; - - if (module) { - preempt_disable(); - /* Note: here, we can fail to get a reference */ - if (likely(module_is_live(module) && - atomic_inc_not_zero(&module->refcnt) != 0)) - trace_module_get(module, _RET_IP_); - else - ret = false; - - preempt_enable(); - } - return ret; -} -EXPORT_SYMBOL(try_module_get); - -void module_put(struct module *module) -{ - int ret; - - if (module) { - preempt_disable(); - ret = atomic_dec_if_positive(&module->refcnt); - WARN_ON(ret < 0); /* Failed to put refcount */ - trace_module_put(module, _RET_IP_); - preempt_enable(); - } -} -EXPORT_SYMBOL(module_put); - -#else /* !CONFIG_MODULE_UNLOAD */ -static inline void print_unload_info(struct seq_file *m, struct module *mod) -{ - /* We don't know the usage count, or what modules are using. */ - seq_puts(m, " - -"); -} - -static inline void module_unload_free(struct module *mod) -{ -} - -static int ref_module(struct module *a, struct module *b) -{ - return strong_try_module_get(b); -} - -static inline int module_unload_init(struct module *mod) -{ - return 0; -} -#endif /* CONFIG_MODULE_UNLOAD */ - -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].c_true; - } - - return l; -} - -static ssize_t show_initstate(struct module_attribute *mattr, - struct module_kobject *mk, char *buffer) -{ - const char *state = "unknown"; - - switch (mk->mod->state) { - case MODULE_STATE_LIVE: - state = "live"; - break; - case MODULE_STATE_COMING: - state = "coming"; - break; - case MODULE_STATE_GOING: - state = "going"; - break; - default: - BUG(); - } - return sprintf(buffer, "%s\n", state); -} - -static struct module_attribute modinfo_initstate = - __ATTR(initstate, 0444, show_initstate, NULL); - -static ssize_t store_uevent(struct module_attribute *mattr, - struct module_kobject *mk, - const char *buffer, size_t count) -{ - int rc; - - rc = kobject_synth_uevent(&mk->kobj, buffer, count); - return rc ? rc : count; -} - -struct module_attribute module_uevent = - __ATTR(uevent, 0200, NULL, store_uevent); - -static ssize_t show_coresize(struct module_attribute *mattr, - struct module_kobject *mk, char *buffer) -{ - return sprintf(buffer, "%u\n", mk->mod->core_layout.size); -} - -static struct module_attribute modinfo_coresize = - __ATTR(coresize, 0444, show_coresize, NULL); - -static ssize_t show_initsize(struct module_attribute *mattr, - struct module_kobject *mk, char *buffer) -{ - return sprintf(buffer, "%u\n", mk->mod->init_layout.size); -} - -static struct module_attribute modinfo_initsize = - __ATTR(initsize, 0444, show_initsize, NULL); - -static ssize_t show_taint(struct module_attribute *mattr, - struct module_kobject *mk, char *buffer) -{ - size_t l; - - l = module_flags_taint(mk->mod, buffer); - buffer[l++] = '\n'; - return l; -} - -static struct module_attribute modinfo_taint = - __ATTR(taint, 0444, show_ta |