3016 lines · 77.4 KB · C
RawDownload
/*   Copyright (C) 2002 Richard Henderson   Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.     This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.     This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.     You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <linux/module.h>#include <linux/moduleloader.h>#include <linux/ftrace_event.h>#include <linux/init.h>#include <linux/kallsyms.h>#include <linux/fs.h>#include <linux/sysfs.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/elf.h>#include <linux/proc_fs.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/stop_machine.h>#include <linux/device.h>#include <linux/string.h>#include <linux/mutex.h>#include <linux/rculist.h>#include <asm/uaccess.h>#include <asm/cacheflush.h>#include <asm/mmu_context.h>#include <linux/license.h>#include <asm/sections.h>#include <linux/tracepoint.h>#include <linux/ftrace.h>#include <linux/async.h>#include <linux/percpu.h>#include <linux/kmemleak.h> #define CREATE_TRACE_POINTS#include <trace/events/module.h> EXPORT_TRACEPOINT_SYMBOL(module_get); #if 0#define DEBUGP printk#else#define DEBUGP(fmt , a...)#endif #ifndef ARCH_SHF_SMALL#define ARCH_SHF_SMALL 0#endif /* If this is set, the section belongs in the init part of the module */#define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) /* List of modules, protected by module_mutex or preempt_disable * (delete uses stop_machine/add uses RCU list operations). */DEFINE_MUTEX(module_mutex);EXPORT_SYMBOL_GPL(module_mutex);static LIST_HEAD(modules); /* Block module loading/unloading? */int modules_disabled = 0; /* Waiting for a module to finish initializing? */static DECLARE_WAIT_QUEUE_HEAD(module_wq); static BLOCKING_NOTIFIER_HEAD(module_notify_list); /* Bounds of module allocation, for speeding __module_address */static unsigned long module_addr_min = -1UL, module_addr_max = 0; 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 failure due to   ongoing or failed initialization etc. */static inline int strong_try_module_get(struct module *mod){	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){	add_taint(flag);	mod->taints |= (1U << 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){	module_put(mod);	do_exit(code);}EXPORT_SYMBOL(__module_put_and_exit); /* Find a module section: 0 means not found. */static unsigned int find_sec(Elf_Ehdr *hdr,			     Elf_Shdr *sechdrs,			     const char *secstrings,			     const char *name){	unsigned int i; 	for (i = 1; i < hdr->e_shnum; i++)		/* Alloc bit cleared means "ignore it." */		if ((sechdrs[i].sh_flags & SHF_ALLOC)		    && strcmp(secstrings+sechdrs[i].sh_name, name) == 0)			return i;	return 0;} /* Find a module section, or NULL. */static void *section_addr(Elf_Ehdr *hdr, Elf_Shdr *shdrs,			  const char *secstrings, const char *name){	/* Section 0 has sh_addr 0. */	return (void *)shdrs[find_sec(hdr, shdrs, secstrings, name)].sh_addr;} /* Find a module section, or NULL.  Fill in number of "objects" in section. */static void *section_objs(Elf_Ehdr *hdr,			  Elf_Shdr *sechdrs,			  const char *secstrings,			  const char *name,			  size_t object_size,			  unsigned int *num){	unsigned int sec = find_sec(hdr, sechdrs, secstrings, name); 	/* Section 0 has sh_addr 0 and sh_size 0. */	*num = sechdrs[sec].sh_size / object_size;	return (void *)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 struct kernel_symbol __start___ksymtab_gpl_future[];extern const struct kernel_symbol __stop___ksymtab_gpl_future[];extern const struct kernel_symbol __start___ksymtab_gpl_future[];extern const struct kernel_symbol __stop___ksymtab_gpl_future[];extern const unsigned long __start___kcrctab[];extern const unsigned long __start___kcrctab_gpl[];extern const unsigned long __start___kcrctab_gpl_future[];#ifdef CONFIG_UNUSED_SYMBOLSextern const struct kernel_symbol __start___ksymtab_unused[];extern const struct kernel_symbol __stop___ksymtab_unused[];extern const struct kernel_symbol __start___ksymtab_unused_gpl[];extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];extern const unsigned long __start___kcrctab_unused[];extern const unsigned long __start___kcrctab_unused_gpl[];#endif #ifndef CONFIG_MODVERSIONS#define symversion(base, idx) NULL#else#define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)#endif static bool each_symbol_in_section(const struct symsearch *arr,				   unsigned int arrsize,				   struct module *owner,				   bool (*fn)(const struct symsearch *syms,					      struct module *owner,					      unsigned int symnum, void *data),				   void *data){	unsigned int i, j; 	for (j = 0; j < arrsize; j++) {		for (i = 0; i < arr[j].stop - arr[j].start; i++)			if (fn(&arr[j], owner, i, data))				return true;	} 	return false;} /* Returns true as soon as fn returns true, otherwise false. */bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner,			    unsigned int symnum, void *data), void *data){	struct module *mod;	const struct symsearch arr[] = {		{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,		  NOT_GPL_ONLY, false },		{ __start___ksymtab_gpl, __stop___ksymtab_gpl,		  __start___kcrctab_gpl,		  GPL_ONLY, false },		{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,		  __start___kcrctab_gpl_future,		  WILL_BE_GPL_ONLY, false },#ifdef CONFIG_UNUSED_SYMBOLS		{ __start___ksymtab_unused, __stop___ksymtab_unused,		  __start___kcrctab_unused,		  NOT_GPL_ONLY, true },		{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,		  __start___kcrctab_unused_gpl,		  GPL_ONLY, true },#endif	}; 	if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))		return true; 	list_for_each_entry_rcu(mod, &modules, list) {		struct symsearch arr[] = {			{ mod->syms, mod->syms + mod->num_syms, mod->crcs,			  NOT_GPL_ONLY, false },			{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,			  mod->gpl_crcs,			  GPL_ONLY, false },			{ mod->gpl_future_syms,			  mod->gpl_future_syms + mod->num_gpl_future_syms,			  mod->gpl_future_crcs,			  WILL_BE_GPL_ONLY, false },#ifdef CONFIG_UNUSED_SYMBOLS			{ mod->unused_syms,			  mod->unused_syms + mod->num_unused_syms,			  mod->unused_crcs,			  NOT_GPL_ONLY, true },			{ mod->unused_gpl_syms,			  mod->unused_gpl_syms + mod->num_unused_gpl_syms,			  mod->unused_gpl_crcs,			  GPL_ONLY, true },#endif		}; 		if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))			return true;	}	return false;}EXPORT_SYMBOL_GPL(each_symbol); struct find_symbol_arg {	/* Input */	const char *name;	bool gplok;	bool warn; 	/* Output */	struct module *owner;	const unsigned long *crc;	const struct kernel_symbol *sym;}; static bool find_symbol_in_section(const struct symsearch *syms,				   struct module *owner,				   unsigned int symnum, void *data){	struct find_symbol_arg *fsa = data; 	if (strcmp(syms->start[symnum].name, fsa->name) != 0)		return false; 	if (!fsa->gplok) {		if (syms->licence == GPL_ONLY)			return false;		if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) {			printk(KERN_WARNING "Symbol %s is being used "			       "by a non-GPL module, which will not "			       "be allowed in the future\n", fsa->name);			printk(KERN_WARNING "Please see the file "			       "Documentation/feature-removal-schedule.txt "			       "in the kernel source tree for more details.\n");		}	} #ifdef CONFIG_UNUSED_SYMBOLS	if (syms->unused && fsa->warn) {		printk(KERN_WARNING "Symbol %s is marked as UNUSED, "		       "however this module is using it.\n", fsa->name);		printk(KERN_WARNING		       "This symbol will go away in the future.\n");		printk(KERN_WARNING		       "Please evalute if this is the right api to use and if "		       "it really is, submit a report the linux kernel "		       "mailinglist together with submitting your code for "		       "inclusion.\n");	}#endif 	fsa->owner = owner;	fsa->crc = symversion(syms->crcs, symnum);	fsa->sym = &syms->start[symnum];	return true;} /* Find a symbol and return it, along with, (optional) crc and * (optional) module which owns it */const struct kernel_symbol *find_symbol(const char *name,					struct module **owner,					const unsigned long **crc,					bool gplok,					bool warn){	struct find_symbol_arg fsa; 	fsa.name = name;	fsa.gplok = gplok;	fsa.warn = warn; 	if (each_symbol(find_symbol_in_section, &fsa)) {		if (owner)			*owner = fsa.owner;		if (crc)			*crc = fsa.crc;		return fsa.sym;	} 	DEBUGP("Failed to find symbol %s\n", name);	return NULL;}EXPORT_SYMBOL_GPL(find_symbol); /* Search for module by name: must hold module_mutex. */struct module *find_module(const char *name){	struct module *mod; 	list_for_each_entry(mod, &modules, list) {		if (strcmp(mod->name, name) == 0)			return mod;	}	return NULL;}EXPORT_SYMBOL_GPL(find_module); #ifdef CONFIG_SMP static void *percpu_modalloc(unsigned long size, unsigned long align,			     const char *name){	void *ptr; 	if (align > PAGE_SIZE) {		printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",		       name, align, PAGE_SIZE);		align = PAGE_SIZE;	} 	ptr = __alloc_reserved_percpu(size, align);	if (!ptr)		printk(KERN_WARNING		       "Could not allocate %lu bytes percpu data\n", size);	return ptr;} static void percpu_modfree(void *freeme){	free_percpu(freeme);} static unsigned int find_pcpusec(Elf_Ehdr *hdr,				 Elf_Shdr *sechdrs,				 const char *secstrings){	return find_sec(hdr, sechdrs, secstrings, ".data.percpu");} static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size){	int cpu; 	for_each_possible_cpu(cpu)		memcpy(pcpudest + per_cpu_offset(cpu), from, size);} #else /* ... !CONFIG_SMP */ static inline void *percpu_modalloc(unsigned long size, unsigned long align,				    const char *name){	return NULL;}static inline void percpu_modfree(void *pcpuptr){	BUG();}static inline unsigned int find_pcpusec(Elf_Ehdr *hdr,					Elf_Shdr *sechdrs,					const char *secstrings){	return 0;}static inline void percpu_modcopy(void *pcpudst, const void *src,				  unsigned long size){	/* pcpusec should be 0, and size of that section should be 0. */	BUG_ON(size != 0);} #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 *mod, char *buffer)             \{                                                                     \	return sprintf(buffer, "%s\n", 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/* Init the unload section of the module. */static void module_unload_init(struct module *mod){	int cpu; 	INIT_LIST_HEAD(&mod->modules_which_use_me);	for_each_possible_cpu(cpu)		local_set(__module_ref_addr(mod, cpu), 0);	/* Hold reference count during initialization. */	local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1);	/* Backwards compatibility macros put refcount during init. */	mod->waiter = current;} /* modules using other modules */struct module_use{	struct list_head list;	struct module *module_which_uses;}; /* 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->modules_which_use_me, list) {		if (use->module_which_uses == a) {			DEBUGP("%s uses %s!\n", a->name, b->name);			return 1;		}

Lines 1–500 of 3016.