4590 lines · 117.2 KB · C
RawDownload
	/* Wait for RCU-sched synchronizing before releasing mod->list. */	synchronize_rcu();	mutex_unlock(&module_mutex); free_module:	/* Free lock-classes; relies on the preceding sync_rcu() */	lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size); 	module_deallocate(mod, info); free_copy:	free_copy(info);	return err;} SYSCALL_DEFINE3(init_module, void __user *, umod,		unsigned long, len, const char __user *, uargs){	int err;	struct load_info info = { }; 	err = may_init_module();	if (err)		return err; 	pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",	       umod, len, uargs); 	err = copy_module_from_user(umod, len, &info);	if (err)		return err; 	return load_module(&info, uargs, 0);} SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags){	struct load_info info = { };	loff_t size;	void *hdr;	int err; 	err = may_init_module();	if (err)		return err; 	pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags); 	if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS		      |MODULE_INIT_IGNORE_VERMAGIC))		return -EINVAL; 	err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX,				       READING_MODULE);	if (err)		return err;	info.hdr = hdr;	info.len = size; 	return load_module(&info, uargs, flags);} static inline int within(unsigned long addr, void *start, unsigned long size){	return ((void *)addr >= start && (void *)addr < start + size);} #ifdef CONFIG_KALLSYMS/* * This ignores the intensely annoying "mapping symbols" found * in ARM ELF files: $a, $t and $d. */static inline int is_arm_mapping_symbol(const char *str){	if (str[0] == '.' && str[1] == 'L')		return true;	return str[0] == '$' && strchr("axtd", str[1])	       && (str[2] == '\0' || str[2] == '.');} static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum){	return kallsyms->strtab + kallsyms->symtab[symnum].st_name;} /* * Given a module and address, find the corresponding symbol and return its name * while providing its size and offset if needed. */static const char *find_kallsyms_symbol(struct module *mod,					unsigned long addr,					unsigned long *size,					unsigned long *offset){	unsigned int i, best = 0;	unsigned long nextval, bestval;	struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); 	/* At worse, next value is at end of module */	if (within_module_init(addr, mod))		nextval = (unsigned long)mod->init_layout.base+mod->init_layout.text_size;	else		nextval = (unsigned long)mod->core_layout.base+mod->core_layout.text_size; 	bestval = kallsyms_symbol_value(&kallsyms->symtab[best]); 	/* Scan for closest preceding symbol, and next symbol. (ELF	   starts real symbols at 1). */	for (i = 1; i < kallsyms->num_symtab; i++) {		const Elf_Sym *sym = &kallsyms->symtab[i];		unsigned long thisval = kallsyms_symbol_value(sym); 		if (sym->st_shndx == SHN_UNDEF)			continue; 		/* We ignore unnamed symbols: they're uninformative		 * and inserted at a whim. */		if (*kallsyms_symbol_name(kallsyms, i) == '\0'		    || is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i)))			continue; 		if (thisval <= addr && thisval > bestval) {			best = i;			bestval = thisval;		}		if (thisval > addr && thisval < nextval)			nextval = thisval;	} 	if (!best)		return NULL; 	if (size)		*size = nextval - bestval;	if (offset)		*offset = addr - bestval; 	return kallsyms_symbol_name(kallsyms, best);} void * __weak dereference_module_function_descriptor(struct module *mod,						     void *ptr){	return ptr;} /* For kallsyms to ask for address resolution.  NULL means not found.  Careful * not to lock to avoid deadlock on oopses, simply disable preemption. */const char *module_address_lookup(unsigned long addr,			    unsigned long *size,			    unsigned long *offset,			    char **modname,			    char *namebuf){	const char *ret = NULL;	struct module *mod; 	preempt_disable();	mod = __module_address(addr);	if (mod) {		if (modname)			*modname = mod->name; 		ret = find_kallsyms_symbol(mod, addr, size, offset);	}	/* Make a copy in here where it's safe */	if (ret) {		strncpy(namebuf, ret, KSYM_NAME_LEN - 1);		ret = namebuf;	}	preempt_enable(); 	return ret;} int lookup_module_symbol_name(unsigned long addr, char *symname){	struct module *mod; 	preempt_disable();	list_for_each_entry_rcu(mod, &modules, list) {		if (mod->state == MODULE_STATE_UNFORMED)			continue;		if (within_module(addr, mod)) {			const char *sym; 			sym = find_kallsyms_symbol(mod, addr, NULL, NULL);			if (!sym)				goto out; 			strlcpy(symname, sym, KSYM_NAME_LEN);			preempt_enable();			return 0;		}	}out:	preempt_enable();	return -ERANGE;} int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,			unsigned long *offset, char *modname, char *name){	struct module *mod; 	preempt_disable();	list_for_each_entry_rcu(mod, &modules, list) {		if (mod->state == MODULE_STATE_UNFORMED)			continue;		if (within_module(addr, mod)) {			const char *sym; 			sym = find_kallsyms_symbol(mod, addr, size, offset);			if (!sym)				goto out;			if (modname)				strlcpy(modname, mod->name, MODULE_NAME_LEN);			if (name)				strlcpy(name, sym, KSYM_NAME_LEN);			preempt_enable();			return 0;		}	}out:	preempt_enable();	return -ERANGE;} int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,			char *name, char *module_name, int *exported){	struct module *mod; 	preempt_disable();	list_for_each_entry_rcu(mod, &modules, list) {		struct mod_kallsyms *kallsyms; 		if (mod->state == MODULE_STATE_UNFORMED)			continue;		kallsyms = rcu_dereference_sched(mod->kallsyms);		if (symnum < kallsyms->num_symtab) {			const Elf_Sym *sym = &kallsyms->symtab[symnum]; 			*value = kallsyms_symbol_value(sym);			*type = kallsyms->typetab[symnum];			strlcpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);			strlcpy(module_name, mod->name, MODULE_NAME_LEN);			*exported = is_exported(name, *value, mod);			preempt_enable();			return 0;		}		symnum -= kallsyms->num_symtab;	}	preempt_enable();	return -ERANGE;} /* Given a module and name of symbol, find and return the symbol's value */static unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name){	unsigned int i;	struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); 	for (i = 0; i < kallsyms->num_symtab; i++) {		const Elf_Sym *sym = &kallsyms->symtab[i]; 		if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 &&		    sym->st_shndx != SHN_UNDEF)			return kallsyms_symbol_value(sym);	}	return 0;} /* Look for this name: can be of form module:name. */unsigned long module_kallsyms_lookup_name(const char *name){	struct module *mod;	char *colon;	unsigned long ret = 0; 	/* Don't lock: we're in enough trouble already. */	preempt_disable();	if ((colon = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) {		if ((mod = find_module_all(name, colon - name, false)) != NULL)			ret = find_kallsyms_symbol_value(mod, colon+1);	} else {		list_for_each_entry_rcu(mod, &modules, list) {			if (mod->state == MODULE_STATE_UNFORMED)				continue;			if ((ret = find_kallsyms_symbol_value(mod, name)) != 0)				break;		}	}	preempt_enable();	return ret;} int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,					     struct module *, unsigned long),				   void *data){	struct module *mod;	unsigned int i;	int ret; 	module_assert_mutex(); 	list_for_each_entry(mod, &modules, list) {		/* We hold module_mutex: no need for rcu_dereference_sched */		struct mod_kallsyms *kallsyms = mod->kallsyms; 		if (mod->state == MODULE_STATE_UNFORMED)			continue;		for (i = 0; i < kallsyms->num_symtab; i++) {			const Elf_Sym *sym = &kallsyms->symtab[i]; 			if (sym->st_shndx == SHN_UNDEF)				continue; 			ret = fn(data, kallsyms_symbol_name(kallsyms, i),				 mod, kallsyms_symbol_value(sym));			if (ret != 0)				return ret;		}	}	return 0;}#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; 	BUG_ON(mod->state == MODULE_STATE_UNFORMED);	if (mod->taints ||	    mod->state == MODULE_STATE_GOING ||	    mod->state == MODULE_STATE_COMING) {		buf[bx++] = '(';		bx += module_flags_taint(mod, buf + bx);		/* Show a - for module-is-being-unloaded */		if (mod->state == MODULE_STATE_GOING)			buf[bx++] = '-';		/* Show a + for module-is-being-loaded */		if (mod->state == MODULE_STATE_COMING)			buf[bx++] = '+';		buf[bx++] = ')';	}	buf[bx] = '\0'; 	return buf;} #ifdef CONFIG_PROC_FS/* Called by the /proc file system to return a list of modules. */static void *m_start(struct seq_file *m, loff_t *pos){	mutex_lock(&module_mutex);	return seq_list_start(&modules, *pos);} static void *m_next(struct seq_file *m, void *p, loff_t *pos){	return seq_list_next(p, &modules, pos);} static void m_stop(struct seq_file *m, void *p){	mutex_unlock(&module_mutex);} static int m_show(struct seq_file *m, void *p){	struct module *mod = list_entry(p, struct module, list);	char buf[MODULE_FLAGS_BUF_SIZE];	void *value; 	/* We always ignore unformed modules. */	if (mod->state == MODULE_STATE_UNFORMED)		return 0; 	seq_printf(m, "%s %u",		   mod->name, mod->init_layout.size + mod->core_layout.size);	print_unload_info(m, mod); 	/* Informative for users. */	seq_printf(m, " %s",		   mod->state == MODULE_STATE_GOING ? "Unloading" :		   mod->state == MODULE_STATE_COMING ? "Loading" :		   "Live");	/* Used by oprofile and other similar tools. */	value = m->private ? NULL : mod->core_layout.base;	seq_printf(m, " 0x%px", value); 	/* Taints info */	if (mod->taints)		seq_printf(m, " %s", module_flags(mod, buf)); 	seq_puts(m, "\n");	return 0;} /* Format: modulename size refcount deps address    Where refcount is a number or -, and deps is a comma-separated list   of depends or -.*/static const struct seq_operations modules_op = {	.start	= m_start,	.next	= m_next,	.stop	= m_stop,	.show	= m_show}; /* * This also sets the "private" pointer to non-NULL if the * kernel pointers should be hidden (so you can just test * "m->private" to see if you should keep the values private). * * We use the same logic as for /proc/kallsyms. */static int modules_open(struct inode *inode, struct file *file){	int err = seq_open(file, &modules_op); 	if (!err) {		struct seq_file *m = file->private_data;		m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul;	} 	return err;} static const struct proc_ops modules_proc_ops = {	.proc_flags	= PROC_ENTRY_PERMANENT,	.proc_open	= modules_open,	.proc_read	= seq_read,	.proc_lseek	= seq_lseek,	.proc_release	= seq_release,}; static int __init proc_modules_init(void){	proc_create("modules", 0, NULL, &modules_proc_ops);	return 0;}module_init(proc_modules_init);#endif /* Given an address, look for it in the module exception tables. */const struct exception_table_entry *search_module_extables(unsigned long addr){	const struct exception_table_entry *e = NULL;	struct module *mod; 	preempt_disable();	mod = __module_address(addr);	if (!mod)		goto out; 	if (!mod->num_exentries)		goto out; 	e = search_extable(mod->extable,			   mod->num_exentries,			   addr);out:	preempt_enable(); 	/*	 * Now, if we found one, we are running inside it now, hence	 * we cannot unload the module, hence no refcnt needed.	 */	return e;} /* * is_module_address - is this address inside a module? * @addr: the address to check. * * See is_module_text_address() if you simply want to see if the address * is code (not data). */bool is_module_address(unsigned long addr){	bool ret; 	preempt_disable();	ret = __module_address(addr) != NULL;	preempt_enable(); 	return ret;} /* * __module_address - get the module which contains an address. * @addr: the address. * * Must be called with preempt disabled or module mutex held so that

Lines 4001–4500 of 4590. Previous lines