3539 lines · 89.7 KB · C
RawDownload
	switch (mk->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 modinfo_initstate =	__ATTR(initstate, 0444, show_initstate, NULL); static ssize_t store_uevent(struct module_attribute *mattr,			    struct module_kobject *mk,			    const char *buffer, size_t count){	enum kobject_action action; 	if (kobject_action_type(buffer, count, &action) == 0)		kobject_uevent(&mk->kobj, action);	return count;} struct module_attribute module_uevent =	__ATTR(uevent, 0200, NULL, store_uevent); static ssize_t show_coresize(struct module_attribute *mattr,			     struct module_kobject *mk, char *buffer){	return sprintf(buffer, "%u\n", mk->mod->core_size);} static struct module_attribute modinfo_coresize =	__ATTR(coresize, 0444, show_coresize, NULL); static ssize_t show_initsize(struct module_attribute *mattr,			     struct module_kobject *mk, char *buffer){	return sprintf(buffer, "%u\n", mk->mod->init_size);} static struct module_attribute modinfo_initsize =	__ATTR(initsize, 0444, show_initsize, NULL); static ssize_t show_taint(struct module_attribute *mattr,			  struct module_kobject *mk, char *buffer){	size_t l; 	l = module_flags_taint(mk->mod, buffer);	buffer[l++] = '\n';	return l;} static struct module_attribute modinfo_taint =	__ATTR(taint, 0444, show_taint, NULL); static struct module_attribute *modinfo_attrs[] = {	&module_uevent,	&modinfo_version,	&modinfo_srcversion,	&modinfo_initstate,	&modinfo_coresize,	&modinfo_initsize,	&modinfo_taint,#ifdef CONFIG_MODULE_UNLOAD	&modinfo_refcnt,#endif	NULL,}; static const char vermagic[] = VERMAGIC_STRING; static int try_to_force_load(struct module *mod, const char *reason){#ifdef CONFIG_MODULE_FORCE_LOAD	if (!test_taint(TAINT_FORCED_MODULE))		printk(KERN_WARNING "%s: %s: kernel tainted.\n",		       mod->name, reason);	add_taint_module(mod, TAINT_FORCED_MODULE);	return 0;#else	return -ENOEXEC;#endif} #ifdef CONFIG_MODVERSIONS/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */static unsigned long maybe_relocated(unsigned long crc,				     const struct module *crc_owner){#ifdef ARCH_RELOCATES_KCRCTAB	if (crc_owner == NULL)		return crc - (unsigned long)reloc_start;#endif	return crc;} static int check_version(Elf_Shdr *sechdrs,			 unsigned int versindex,			 const char *symname,			 struct module *mod, 			 const unsigned long *crc,			 const struct module *crc_owner){	unsigned int i, num_versions;	struct modversion_info *versions; 	/* Exporting module didn't supply crcs?  OK, we're already tainted. */	if (!crc)		return 1; 	/* No versions at all?  modprobe --force does this. */	if (versindex == 0)		return try_to_force_load(mod, symname) == 0; 	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 == maybe_relocated(*crc, crc_owner))			return 1;		pr_debug("Found checksum %lX vs module %lX\n",		       maybe_relocated(*crc, crc_owner), versions[i].crc);		goto bad_version;	} 	printk(KERN_WARNING "%s: no symbol version for %s\n",	       mod->name, symname);	return 0; bad_version:	printk("%s: disagrees about version of symbol %s\n",	       mod->name, symname);	return 0;} static inline int check_modstruct_version(Elf_Shdr *sechdrs,					  unsigned int versindex,					  struct module *mod){	const unsigned long *crc; 	/* Since this should be found in kernel (which can't be removed),	 * no locking is necessary. */	if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,			 &crc, true, false))		BUG();	return check_version(sechdrs, versindex, "module_layout", mod, crc,			     NULL);} /* First part is kernel version, which we ignore if module has crcs. */static inline int same_magic(const char *amagic, const char *bmagic,			     bool has_crcs){	if (has_crcs) {		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,				const struct module *crc_owner){	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. */static const struct kernel_symbol *resolve_symbol(struct module *mod,						  const struct load_info *info,						  const char *name,						  char ownername[]){	struct module *owner;	const struct kernel_symbol *sym;	const unsigned long *crc;	int err; 	mutex_lock(&module_mutex);	sym = find_symbol(name, &owner, &crc,			  !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);	if (!sym)		goto unlock; 	if (!check_version(info->sechdrs, info->index.vers, name, mod, crc,			   owner)) {		sym = ERR_PTR(-EINVAL);		goto getname;	} 	err = ref_module(mod, owner);	if (err) {		sym = ERR_PTR(err);		goto getname;	} getname:	/* We must make copy under the lock if we failed to get ref. */	strncpy(ownername, module_name(owner), MODULE_NAME_LEN);unlock:	mutex_unlock(&module_mutex);	return sym;} static const struct kernel_symbol *resolve_symbol_wait(struct module *mod,		    const struct load_info *info,		    const char *name){	const struct kernel_symbol *ksym;	char owner[MODULE_NAME_LEN]; 	if (wait_event_interruptible_timeout(module_wq,			!IS_ERR(ksym = resolve_symbol(mod, info, name, owner))			|| PTR_ERR(ksym) != -EBUSY,					     30 * HZ) <= 0) {		printk(KERN_WARNING "%s: gave up waiting for init of module %s.\n",		       mod->name, owner);	}	return ksym;} /* * /sys/module/foo/sections stuff * J. Corbet <corbet@lwn.net> */#ifdef CONFIG_SYSFS #ifdef CONFIG_KALLSYMSstatic inline bool sect_empty(const Elf_Shdr *sect){	return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;} 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_kobject *mk, char *buf){	struct module_sect_attr *sattr =		container_of(mattr, struct module_sect_attr, mattr);	return sprintf(buf, "0x%pK\n", (void *)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, const struct load_info *info){	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 < info->hdr->e_shnum; i++)		if (!sect_empty(&info->sechdrs[i]))			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 < info->hdr->e_shnum; i++) {		Elf_Shdr *sec = &info->sechdrs[i];		if (sect_empty(sec))			continue;		sattr->address = sec->sh_addr;		sattr->name = kstrdup(info->secstrings + sec->sh_name,					GFP_KERNEL);		if (sattr->name == NULL)			goto out;		sect_attrs->nsections++;		sysfs_attr_init(&sattr->mattr.attr);		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 file *filp, 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, const struct load_info *info){	unsigned int notes, loaded, i;	struct module_notes_attrs *notes_attrs;	struct bin_attribute *nattr; 	/* failed to create section attributes, so can't create notes */	if (!mod->sect_attrs)		return; 	/* Count notes sections and allocate structures.  */	notes = 0;	for (i = 0; i < info->hdr->e_shnum; i++)		if (!sect_empty(&info->sechdrs[i]) &&		    (info->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 < info->hdr->e_shnum; ++i) {		if (sect_empty(&info->sechdrs[i]))			continue;		if (info->sechdrs[i].sh_type == SHT_NOTE) {			sysfs_bin_attr_init(nattr);			nattr->attr.name = mod->sect_attrs->attrs[loaded].name;			nattr->attr.mode = S_IRUGO;			nattr->size = info->sechdrs[i].sh_size;			nattr->private = (void *) info->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);} #else static inline void add_sect_attrs(struct module *mod,				  const struct load_info *info){} static inline void remove_sect_attrs(struct module *mod){} static inline void add_notes_attrs(struct module *mod,				   const struct load_info *info){} static inline void remove_notes_attrs(struct module *mod){}#endif /* CONFIG_KALLSYMS */ static void add_usage_links(struct module *mod){#ifdef CONFIG_MODULE_UNLOAD	struct module_use *use;	int nowarn; 	mutex_lock(&module_mutex);	list_for_each_entry(use, &mod->target_list, target_list) {		nowarn = sysfs_create_link(use->target->holders_dir,					   &mod->mkobj.kobj, mod->name);	}	mutex_unlock(&module_mutex);#endif} static void del_usage_links(struct module *mod){#ifdef CONFIG_MODULE_UNLOAD	struct module_use *use; 	mutex_lock(&module_mutex);

Lines 1001–1500 of 3539. Previous lines