⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 5 页
字号:
MODINFO_ATTR(srcversion);#ifdef CONFIG_MODULE_UNLOAD/* Init the unload section of the module. */static void module_unload_init(struct module *mod){	unsigned int i;	INIT_LIST_HEAD(&mod->modules_which_use_me);	for (i = 0; i < NR_CPUS; i++)		local_set(&mod->ref[i].count, 0);	/* Hold reference count during initialization. */	local_set(&mod->ref[raw_smp_processor_id()].count, 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;		}	}	DEBUGP("%s does not use %s!\n", a->name, b->name);	return 0;}/* Module a uses b */static int use_module(struct module *a, struct module *b){	struct module_use *use;	int no_warn;	if (b == NULL || already_uses(a, b)) return 1;	if (!strong_try_module_get(b))		return 0;	DEBUGP("Allocating new usage for %s.\n", a->name);	use = kmalloc(sizeof(*use), GFP_ATOMIC);	if (!use) {		printk("%s: out of memory loading\n", a->name);		module_put(b);		return 0;	}	use->module_which_uses = a;	list_add(&use->list, &b->modules_which_use_me);	no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name);	return 1;}/* Clear the unload stuff of the module. */static void module_unload_free(struct module *mod){	struct module *i;	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);				sysfs_remove_link(i->holders_dir, mod->name);				/* 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,};void module_put(struct module *module){	if (module) {		unsigned int cpu = get_cpu();		local_dec(&module->ref[cpu].count);		/* Maybe they're waiting for us to drop reference? */		if (unlikely(!module_is_live(module)))			wake_up_process(module->waiter);		put_cpu();	}}EXPORT_SYMBOL(module_put);#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 ssize_t show_initstate(struct module_attribute *mattr,			   struct module *mod, char *buffer){	const char *state = "unknown";	switch (mod->state) {	case MODULE_STATE_LIVE:		state = "live";		break;	case MODULE_STATE_COMING:		state = "coming";		break;	case MODULE_STATE_GOING:		state = "going";		break;	}	return sprintf(buffer, "%s\n", state);}static struct module_attribute initstate = {	.attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },	.show = show_initstate,};static struct module_attribute *modinfo_attrs[] = {	&modinfo_version,	&modinfo_srcversion,	&initstate,#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_module(mod, 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->taints & TAINT_PROPRIETARY_MODULE));	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 free_sect_attrs(struct module_sect_attrs *sect_attrs){	int section;	for (section = 0; section < sect_attrs->nsections; section++)		kfree(sect_attrs->attrs[section].name);	kfree(sect_attrs);}static void add_sect_attrs(struct module *mod, unsigned int nsect,		char *secstrings, Elf_Shdr *sechdrs){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -