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

📄 module.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 5 页
字号:
		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,			     bool has_crcs){	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), true);	if (!IS_ERR_VALUE(ret)) {		/* use_module can fail due to OOM,		   or module initialization or unloading */		if (!check_version(sechdrs, versindex, name, mod, crc) ||		    !use_module(mod, owner))			ret = -EINVAL;	}	return ret;}/* * /sys/module/foo/sections stuff * J. Corbet <corbet@lwn.net> */#if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS)struct module_sect_attr{	struct module_attribute mattr;	char *name;	unsigned long address;};struct module_sect_attrs{	struct attribute_group grp;	unsigned int nsections;	struct module_sect_attr attrs[0];};static 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){	unsigned 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){	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]);	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);	if (sect_attrs == NULL)		return;	/* Setup section attributes. */	sect_attrs->grp.name = "sections";	sect_attrs->grp.attrs = (void *)sect_attrs + size[0];	sect_attrs->nsections = 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;		sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,					GFP_KERNEL);		if (sattr->name == NULL)			goto out;		sect_attrs->nsections++;		sattr->mattr.show = module_sect_show;		sattr->mattr.store = NULL;		sattr->mattr.attr.name = sattr->name;		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:	free_sect_attrs(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. */		free_sect_attrs(mod->sect_attrs);		mod->sect_attrs = NULL;	}}/* * /sys/module/foo/notes/.section.name gives contents of SHT_NOTE sections. */struct module_notes_attrs {	struct kobject *dir;	unsigned int notes;	struct bin_attribute attrs[0];};static ssize_t module_notes_read(struct kobject *kobj,				 struct bin_attribute *bin_attr,				 char *buf, loff_t pos, size_t count){	/*	 * The caller checked the pos and count against our size.	 */	memcpy(buf, bin_attr->private + pos, count);	return count;}static void free_notes_attrs(struct module_notes_attrs *notes_attrs,			     unsigned int i){	if (notes_attrs->dir) {		while (i-- > 0)			sysfs_remove_bin_file(notes_attrs->dir,					      &notes_attrs->attrs[i]);		kobject_put(notes_attrs->dir);	}	kfree(notes_attrs);}static void add_notes_attrs(struct module *mod, unsigned int nsect,			    char *secstrings, Elf_Shdr *sechdrs){	unsigned int notes, loaded, i;	struct module_notes_attrs *notes_attrs;	struct bin_attribute *nattr;	/* Count notes sections and allocate structures.  */	notes = 0;	for (i = 0; i < nsect; i++)		if ((sechdrs[i].sh_flags & SHF_ALLOC) &&		    (sechdrs[i].sh_type == SHT_NOTE))			++notes;	if (notes == 0)		return;	notes_attrs = kzalloc(sizeof(*notes_attrs)			      + notes * sizeof(notes_attrs->attrs[0]),			      GFP_KERNEL);	if (notes_attrs == NULL)		return;	notes_attrs->notes = notes;	nattr = &notes_attrs->attrs[0];	for (loaded = i = 0; i < nsect; ++i) {		if (!(sechdrs[i].sh_flags & SHF_ALLOC))			continue;		if (sechdrs[i].sh_type == SHT_NOTE) {			nattr->attr.name = mod->sect_attrs->attrs[loaded].name;			nattr->attr.mode = S_IRUGO;			nattr->size = sechdrs[i].sh_size;			nattr->private = (void *) sechdrs[i].sh_addr;			nattr->read = module_notes_read;			++nattr;		}		++loaded;	}	notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);	if (!notes_attrs->dir)		goto out;	for (i = 0; i < notes; ++i)		if (sysfs_create_bin_file(notes_attrs->dir,					  &notes_attrs->attrs[i]))			goto out;	mod->notes_attrs = notes_attrs;	return;  out:	free_notes_attrs(notes_attrs, i);}static void remove_notes_attrs(struct module *mod){	if (mod->notes_attrs)		free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);}#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){}static inline void add_notes_attrs(struct module *mod, unsigned int nsect,				   char *sectstrings, Elf_Shdr *sechdrs){}static inline void remove_notes_attrs(struct module *mod){}#endif#ifdef CONFIG_SYSFSint 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));			error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);			++temp_attr;		}	}	return error;}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);}int mod_sysfs_init(struct module *mod){	int err;	struct kobject *kobj;	if (!module_sysfs_initialized) {		printk(KERN_ERR "%s: module sysfs not initialized\n",		       mod->name);		err = -EINVAL;		goto out;	}	kobj = kset_find_obj(module_kset, mod->name);	if (kobj) {		printk(KERN_ERR "%s: module is already loaded\n", mod->name);		kobject_put(kobj);		err = -EINVAL;		goto out;	}	mod->mkobj.mod = mod;	memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));	mod->mkobj.kobj.kset = module_kset;	err = kobject_init_and_add(&mod->mkobj.kobj, &module_ktype, NULL,				   "%s", mod->name);	if (err)		kobject_put(&mod->mkobj.kobj);	/* delay uevent until full sysfs population */out:	return err;}int mod_sysfs_setup(struct module *mod,			   struct kernel_param *kparam,			   unsigned int num_params){	int err;	mod->holders_dir = kobject_create_and_add("holders", &mod->mkobj.kobj);	if (!mod->holders_dir) {		err = -ENOMEM;		goto out_unreg;	}	err = module_param_sysfs_setup(mod, kparam, num_params);	if (err)		goto out_unreg_holders;	err = module_add_modinfo_attrs(mod);	if (err)		goto out_unreg_param;	kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);	return 0;out_unreg_param:	module_param_sysfs_remove(mod);out_unreg_holders:	kobject_put(mod->holders_dir);out_unreg:	kobject_put(&mod->mkobj.kobj);	return err;}static void mod_sysfs_fini(struct module *mod){	kobject_put(&mod->mkobj.kobj);}#else /* CONFIG_SYSFS */static void mod_sysfs_fini(struct module *mod){}#endif /* CONFIG_SYSFS */static void mod_kobject_remove(struct module *mod){	module_remove_modinfo_attrs(mod);	module_param_sysfs_remove(mod);	kobject_put(mod->mkobj.drivers_dir);	kobject_put(mod->holders_dir);	mod_sysfs_fini(mod);}/* * link the module with the whole machine is stopped with interrupts off * - this defends against kallsyms not taking locks */static int __link_module(void *_mod){	struct module *mod = _mod;	list_add(&mod->list, &modules);	return 0;}/* * unlink the module with the whole machine is stopped with interrupts off * - this defends against kallsyms not taking locks */static int __unlink_module(void *_mod){	struct module *mod = _mod;	list_del(&mod->list);	return 0;}/* Free a module, remove from lists, etc (must hold module_mutex). */static void free_module(struct module *mod){	/* Delete from various lists */	stop_machine(__unlink_module, mod, NULL);	remove_notes_attrs(mod);	remove_sect_attrs(mod);	mod_kobject_remove(mod);	unwind_remove_table(mod->unwind_info, 0);	/* Arch-specific cleanup. */	module_arch_cleanup(mod);	/* Module unload stuff */	module_unload_free(mod);	/* This may be NULL, but that's OK */	module_free(mod, mod->module_init);	kfree(mod->args);	if (mod->percpu)		percpu_modfree(mod->percpu);	/* Free lock-classes: */	lockdep_free_key_range(mod->module_core, mod->core_size);	/* Finally, free the core (containing the module structure) */	module_free(mod, mod->module_core);}void *__symbol_get(const char *symbol){	struct module *owner;	unsigned long value;	preempt_disable();	value = find_symbol(symbol, &owner, NULL, true, true);	if (IS_ERR_VALUE(value))		value = 0;	else if (strong_try_module_get(owner))		value = 0;	preempt_enable();	return (void *)value;}EXPORT_SYMBOL_GPL(__symbol_get);/* * Ensure that an exported symbol [global namespace] does not already exist * in the kernel or in some other module's exported symbol table. */static int verify_export_symbols(struct module *mod){	unsigned int i;	struct module *owner;	const struct kernel_symbol *s;	struct {		const struct kernel_symbol *sym;		unsigned int num;	} arr[] = {		{ mod->syms, mod->num_syms },		{ mod->gpl_syms, mod->num_gpl_syms },		{ mod->gpl_future_syms, mod->num_gpl_future_syms },#ifdef CONFIG_UNUSED_SYMBOLS		{ mod->unused_syms, mod->num_unused_syms },		{ mod->unused_gpl_syms, mod->num_unused_gpl_syms },#endif	};	for (i = 0; i < ARRAY_SIZE(arr); i++) {		for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {			if (!IS_ERR_VALUE(find_symbol(s->name, &owner,						      NULL, true, false))) {				printk(KERN_ERR				       "%s: exports duplicate symbol %s"				       " (owned by %s)\n",				       mod->name, s->name, module_name(owner));

⌨️ 快捷键说明

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