2126 lines · 54.9 KB · C
RawDownload
	list_for_each_entry(i, &modules, list) {		struct module_use *use; 		list_for_each_entry(use, &i->modules_which_use_me, list) {			if (use->module_which_uses == mod) {				DEBUGP("%s unusing %s\n", mod->name, i->name);				module_put(i);				list_del(&use->list);				kfree(use);				/* There can be at most one match. */				break;			}		}	}} #ifdef CONFIG_MODULE_FORCE_UNLOADstatic inline int try_force_unload(unsigned int flags){	int ret = (flags & O_TRUNC);	if (ret)		add_taint(TAINT_FORCED_RMMOD);	return ret;}#elsestatic inline int try_force_unload(unsigned int flags){	return 0;}#endif /* CONFIG_MODULE_FORCE_UNLOAD */ struct stopref{	struct module *mod;	int flags;	int *forced;}; /* Whole machine is stopped with interrupts off when this runs. */static int __try_stop_module(void *_sref){	struct stopref *sref = _sref; 	/* If it's not unused, quit unless we are told to block. */	if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) {		if (!(*sref->forced = try_force_unload(sref->flags)))			return -EWOULDBLOCK;	} 	/* Mark it as dying. */	sref->mod->state = MODULE_STATE_GOING;	return 0;} static int try_stop_module(struct module *mod, int flags, int *forced){	struct stopref sref = { mod, flags, forced }; 	return stop_machine_run(__try_stop_module, &sref, NR_CPUS);} unsigned int module_refcount(struct module *mod){	unsigned int i, total = 0; 	for (i = 0; i < NR_CPUS; i++)		total += local_read(&mod->ref[i].count);	return total;}EXPORT_SYMBOL(module_refcount); /* This exists whether we can unload or not */static void free_module(struct module *mod); static void wait_for_zero_refcount(struct module *mod){	/* Since we might sleep for some time, drop the semaphore first */	mutex_unlock(&module_mutex);	for (;;) {		DEBUGP("Looking at refcount...\n");		set_current_state(TASK_UNINTERRUPTIBLE);		if (module_refcount(mod) == 0)			break;		schedule();	}	current->state = TASK_RUNNING;	mutex_lock(&module_mutex);} asmlinkage longsys_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))		return -EPERM; 	if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)		return -EFAULT;	name[MODULE_NAME_LEN-1] = '\0'; 	if (mutex_lock_interruptible(&module_mutex) != 0)		return -EINTR; 	mod = find_module(name);	if (!mod) {		ret = -ENOENT;		goto out;	} 	if (!list_empty(&mod->modules_which_use_me)) {		/* 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 and wake up                   waiter --RR */		DEBUGP("%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 != NULL && mod->exit == NULL)	    || mod->unsafe) {		forced = try_force_unload(flags);		if (!forced) {			/* This module can't be removed */			ret = -EBUSY;			goto out;		}	} 	/* Set this up before setting mod->state */	mod->waiter = current; 	/* Stop the machine so refcounts can't move and disable module. */	ret = try_stop_module(mod, flags, &forced);	if (ret != 0)		goto out; 	/* Never wait if forced. */	if (!forced && module_refcount(mod) != 0)		wait_for_zero_refcount(mod); 	/* Final destruction now noone is using it. */	if (mod->exit != NULL) {		mutex_unlock(&module_mutex);		mod->exit();		mutex_lock(&module_mutex);	}	free_module(mod);  out:	mutex_unlock(&module_mutex);	return ret;} static void print_unload_info(struct seq_file *m, struct module *mod){	struct module_use *use;	int printed_something = 0; 	seq_printf(m, " %u ", 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->modules_which_use_me, list) {		printed_something = 1;		seq_printf(m, "%s,", use->module_which_uses->name);	} 	if (mod->unsafe) {		printed_something = 1;		seq_printf(m, "[unsafe],");	} 	if (mod->init != NULL && mod->exit == NULL) {		printed_something = 1;		seq_printf(m, "[permanent],");	} 	if (!printed_something)		seq_printf(m, "-");} void __symbol_put(const char *symbol){	struct module *owner;	unsigned long flags;	const unsigned long *crc; 	spin_lock_irqsave(&modlist_lock, flags);	if (!__find_symbol(symbol, &owner, &crc, 1))		BUG();	module_put(owner);	spin_unlock_irqrestore(&modlist_lock, flags);}EXPORT_SYMBOL(__symbol_put); void symbol_put_addr(void *addr){	struct module *modaddr; 	if (core_kernel_text((unsigned long)addr))		return; 	if (!(modaddr = module_text_address((unsigned long)addr)))		BUG();	module_put(modaddr);}EXPORT_SYMBOL_GPL(symbol_put_addr); static ssize_t show_refcnt(struct module_attribute *mattr,			   struct module *mod, char *buffer){	/* sysfs holds a reference */	return sprintf(buffer, "%u\n", module_refcount(mod)-1);} static struct module_attribute refcnt = {	.attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },	.show = show_refcnt,}; #else /* !CONFIG_MODULE_UNLOAD */static void print_unload_info(struct seq_file *m, struct module *mod){	/* We don't know the usage count, or what modules are using. */	seq_printf(m, " - -");} static inline void module_unload_free(struct module *mod){} static inline int use_module(struct module *a, struct module *b){	return strong_try_module_get(b);} static inline void module_unload_init(struct module *mod){}#endif /* CONFIG_MODULE_UNLOAD */ static struct module_attribute *modinfo_attrs[] = {	&modinfo_version,	&modinfo_srcversion,#ifdef CONFIG_MODULE_UNLOAD	&refcnt,#endif	NULL,}; static const char vermagic[] = VERMAGIC_STRING; #ifdef CONFIG_MODVERSIONSstatic int check_version(Elf_Shdr *sechdrs,			 unsigned int versindex,			 const char *symname,			 struct module *mod, 			 const unsigned long *crc){	unsigned int i, num_versions;	struct modversion_info *versions; 	/* Exporting module didn't supply crcs?  OK, we're already tainted. */	if (!crc)		return 1; 	versions = (void *) sechdrs[versindex].sh_addr;	num_versions = sechdrs[versindex].sh_size		/ sizeof(struct modversion_info); 	for (i = 0; i < num_versions; i++) {		if (strcmp(versions[i].name, symname) != 0)			continue; 		if (versions[i].crc == *crc)			return 1;		printk("%s: disagrees about version of symbol %s\n",		       mod->name, symname);		DEBUGP("Found checksum %lX vs module %lX\n",		       *crc, versions[i].crc);		return 0;	}	/* Not in module's version table.  OK, but that taints the kernel. */	if (!(tainted & TAINT_FORCED_MODULE)) {		printk("%s: no version for \"%s\" found: kernel tainted.\n",		       mod->name, symname);		add_taint(TAINT_FORCED_MODULE);	}	return 1;} static inline int check_modstruct_version(Elf_Shdr *sechdrs,					  unsigned int versindex,					  struct module *mod){	const unsigned long *crc;	struct module *owner; 	if (!__find_symbol("struct_module", &owner, &crc, 1))		BUG();	return check_version(sechdrs, versindex, "struct_module", mod,			     crc);} /* First part is kernel version, which we ignore. */static inline int same_magic(const char *amagic, const char *bmagic){	amagic += strcspn(amagic, " ");	bmagic += strcspn(bmagic, " ");	return strcmp(amagic, bmagic) == 0;}#elsestatic inline int check_version(Elf_Shdr *sechdrs,				unsigned int versindex,				const char *symname,				struct module *mod, 				const unsigned long *crc){	return 1;} static inline int check_modstruct_version(Elf_Shdr *sechdrs,					  unsigned int versindex,					  struct module *mod){	return 1;} static inline int same_magic(const char *amagic, const char *bmagic){	return strcmp(amagic, bmagic) == 0;}#endif /* CONFIG_MODVERSIONS */ /* Resolve a symbol for this module.  I.e. if we find one, record usage.   Must be holding module_mutex. */static unsigned long resolve_symbol(Elf_Shdr *sechdrs,				    unsigned int versindex,				    const char *name,				    struct module *mod){	struct module *owner;	unsigned long ret;	const unsigned long *crc; 	ret = __find_symbol(name, &owner, &crc, mod->license_gplok);	if (ret) {		/* use_module can fail due to OOM, or module unloading */		if (!check_version(sechdrs, versindex, name, mod, crc) ||		    !use_module(mod, owner))			ret = 0;	}	return ret;}  /* * /sys/module/foo/sections stuff * J. Corbet <corbet@lwn.net> */#ifdef CONFIG_KALLSYMSstatic ssize_t module_sect_show(struct module_attribute *mattr,				struct module *mod, char *buf){	struct module_sect_attr *sattr =		container_of(mattr, struct module_sect_attr, mattr);	return sprintf(buf, "0x%lx\n", sattr->address);} static void add_sect_attrs(struct module *mod, unsigned int nsect,		char *secstrings, Elf_Shdr *sechdrs){	unsigned int nloaded = 0, i, size[2];	struct module_sect_attrs *sect_attrs;	struct module_sect_attr *sattr;	struct attribute **gattr;		/* Count loaded sections and allocate structures */	for (i = 0; i < nsect; i++)		if (sechdrs[i].sh_flags & SHF_ALLOC)			nloaded++;	size[0] = ALIGN(sizeof(*sect_attrs)			+ nloaded * sizeof(sect_attrs->attrs[0]),			sizeof(sect_attrs->grp.attrs[0]));	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);	if (! (sect_attrs = kmalloc(size[0] + size[1], GFP_KERNEL)))		return; 	/* Setup section attributes. */	sect_attrs->grp.name = "sections";	sect_attrs->grp.attrs = (void *)sect_attrs + size[0]; 	sattr = &sect_attrs->attrs[0];	gattr = &sect_attrs->grp.attrs[0];	for (i = 0; i < nsect; i++) {		if (! (sechdrs[i].sh_flags & SHF_ALLOC))			continue;		sattr->address = sechdrs[i].sh_addr;		strlcpy(sattr->name, secstrings + sechdrs[i].sh_name,			MODULE_SECT_NAME_LEN);		sattr->mattr.show = module_sect_show;		sattr->mattr.store = NULL;		sattr->mattr.attr.name = sattr->name;		sattr->mattr.attr.owner = mod;		sattr->mattr.attr.mode = S_IRUGO;		*(gattr++) = &(sattr++)->mattr.attr;	}	*gattr = NULL; 	if (sysfs_create_group(&mod->mkobj.kobj, &sect_attrs->grp))		goto out; 	mod->sect_attrs = sect_attrs;	return;  out:	kfree(sect_attrs);} static void remove_sect_attrs(struct module *mod){	if (mod->sect_attrs) {		sysfs_remove_group(&mod->mkobj.kobj,				   &mod->sect_attrs->grp);		/* We are positive that no one is using any sect attrs		 * at this point.  Deallocate immediately. */		kfree(mod->sect_attrs);		mod->sect_attrs = NULL;	}}  #elsestatic inline void add_sect_attrs(struct module *mod, unsigned int nsect,		char *sectstrings, Elf_Shdr *sechdrs){} static inline void remove_sect_attrs(struct module *mod){}#endif /* CONFIG_KALLSYMS */ static int module_add_modinfo_attrs(struct module *mod){	struct module_attribute *attr;	struct module_attribute *temp_attr;	int error = 0;	int i; 	mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *					(ARRAY_SIZE(modinfo_attrs) + 1)),					GFP_KERNEL);	if (!mod->modinfo_attrs)		return -ENOMEM; 	temp_attr = mod->modinfo_attrs;	for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {		if (!attr->test ||		    (attr->test && attr->test(mod))) {			memcpy(temp_attr, attr, sizeof(*temp_attr));			temp_attr->attr.owner = mod;			error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);			++temp_attr;		}	}	return error;} static void module_remove_modinfo_attrs(struct module *mod){	struct module_attribute *attr;	int i; 	for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {		/* pick a field to test for end of list */		if (!attr->attr.name)			break;		sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);		if (attr->free)			attr->free(mod);	}	kfree(mod->modinfo_attrs);} static int mod_sysfs_setup(struct module *mod,			   struct kernel_param *kparam,			   unsigned int num_params){	int err; 

Lines 501–1000 of 2126. Previous lines