diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 205 | 
1 files changed, 110 insertions, 95 deletions
| diff --git a/kernel/module.c b/kernel/module.c index 178333c48d1e..2c932760fd33 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -62,12 +62,6 @@  #define CREATE_TRACE_POINTS  #include <trace/events/module.h> -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt , a...) -#endif -  #ifndef ARCH_SHF_SMALL  #define ARCH_SHF_SMALL 0  #endif @@ -138,7 +132,6 @@ struct load_info {  	unsigned long len;  	Elf_Shdr *sechdrs;  	char *secstrings, *strtab; -	unsigned long *strmap;  	unsigned long symoffs, stroffs;  	struct _ddebug *debug;  	unsigned int num_debug; @@ -410,7 +403,7 @@ const struct kernel_symbol *find_symbol(const char *name,  		return fsa.sym;  	} -	DEBUGP("Failed to find symbol %s\n", name); +	pr_debug("Failed to find symbol %s\n", name);  	return NULL;  }  EXPORT_SYMBOL_GPL(find_symbol); @@ -600,11 +593,11 @@ static int already_uses(struct module *a, struct module *b)  	list_for_each_entry(use, &b->source_list, source_list) {  		if (use->source == a) { -			DEBUGP("%s uses %s!\n", a->name, b->name); +			pr_debug("%s uses %s!\n", a->name, b->name);  			return 1;  		}  	} -	DEBUGP("%s does not use %s!\n", a->name, b->name); +	pr_debug("%s does not use %s!\n", a->name, b->name);  	return 0;  } @@ -619,7 +612,7 @@ static int add_module_usage(struct module *a, struct module *b)  {  	struct module_use *use; -	DEBUGP("Allocating new usage for %s.\n", a->name); +	pr_debug("Allocating new usage for %s.\n", a->name);  	use = kmalloc(sizeof(*use), GFP_ATOMIC);  	if (!use) {  		printk(KERN_WARNING "%s: out of memory loading\n", a->name); @@ -663,7 +656,7 @@ static void module_unload_free(struct module *mod)  	mutex_lock(&module_mutex);  	list_for_each_entry_safe(use, tmp, &mod->target_list, target_list) {  		struct module *i = use->target; -		DEBUGP("%s unusing %s\n", mod->name, i->name); +		pr_debug("%s unusing %s\n", mod->name, i->name);  		module_put(i);  		list_del(&use->source_list);  		list_del(&use->target_list); @@ -726,9 +719,9 @@ static int try_stop_module(struct module *mod, int flags, int *forced)  	}  } -unsigned int module_refcount(struct module *mod) +unsigned long module_refcount(struct module *mod)  { -	unsigned int incs = 0, decs = 0; +	unsigned long incs = 0, decs = 0;  	int cpu;  	for_each_possible_cpu(cpu) @@ -761,7 +754,7 @@ static void wait_for_zero_refcount(struct module *mod)  	/* Since we might sleep for some time, release the mutex first */  	mutex_unlock(&module_mutex);  	for (;;) { -		DEBUGP("Looking at refcount...\n"); +		pr_debug("Looking at refcount...\n");  		set_current_state(TASK_UNINTERRUPTIBLE);  		if (module_refcount(mod) == 0)  			break; @@ -804,7 +797,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,  	if (mod->state != MODULE_STATE_LIVE) {  		/* FIXME: if (force), slam module count and wake up                     waiter --RR */ -		DEBUGP("%s already dying\n", mod->name); +		pr_debug("%s already dying\n", mod->name);  		ret = -EBUSY;  		goto out;  	} @@ -854,7 +847,7 @@ static inline 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)); +	seq_printf(m, " %lu ", module_refcount(mod));  	/* Always include a trailing , so userspace can differentiate             between this and the old multi-field proc format. */ @@ -904,13 +897,11 @@ EXPORT_SYMBOL_GPL(symbol_put_addr);  static ssize_t show_refcnt(struct module_attribute *mattr,  			   struct module_kobject *mk, char *buffer)  { -	return sprintf(buffer, "%u\n", module_refcount(mk->mod)); +	return sprintf(buffer, "%lu\n", module_refcount(mk->mod));  } -static struct module_attribute refcnt = { -	.attr = { .name = "refcnt", .mode = 0444 }, -	.show = show_refcnt, -}; +static struct module_attribute modinfo_refcnt = +	__ATTR(refcnt, 0444, show_refcnt, NULL);  void module_put(struct module *module)  { @@ -951,6 +942,26 @@ static inline int module_unload_init(struct module *mod)  }  #endif /* CONFIG_MODULE_UNLOAD */ +static size_t module_flags_taint(struct module *mod, char *buf) +{ +	size_t l = 0; + +	if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE)) +		buf[l++] = 'P'; +	if (mod->taints & (1 << TAINT_OOT_MODULE)) +		buf[l++] = 'O'; +	if (mod->taints & (1 << TAINT_FORCED_MODULE)) +		buf[l++] = 'F'; +	if (mod->taints & (1 << TAINT_CRAP)) +		buf[l++] = 'C'; +	/* +	 * TAINT_FORCED_RMMOD: could be added. +	 * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't +	 * apply to modules. +	 */ +	return l; +} +  static ssize_t show_initstate(struct module_attribute *mattr,  			      struct module_kobject *mk, char *buffer)  { @@ -970,10 +981,8 @@ static ssize_t show_initstate(struct module_attribute *mattr,  	return sprintf(buffer, "%s\n", state);  } -static struct module_attribute initstate = { -	.attr = { .name = "initstate", .mode = 0444 }, -	.show = show_initstate, -}; +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, @@ -986,18 +995,50 @@ static ssize_t store_uevent(struct module_attribute *mattr,  	return count;  } -struct module_attribute module_uevent = { -	.attr = { .name = "uevent", .mode = 0200 }, -	.store = store_uevent, -}; +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, -	&initstate, -	&module_uevent, +	&modinfo_initstate, +	&modinfo_coresize, +	&modinfo_initsize, +	&modinfo_taint,  #ifdef CONFIG_MODULE_UNLOAD -	&refcnt, +	&modinfo_refcnt,  #endif  	NULL,  }; @@ -1057,7 +1098,7 @@ static int check_version(Elf_Shdr *sechdrs,  		if (versions[i].crc == maybe_relocated(*crc, crc_owner))  			return 1; -		DEBUGP("Found checksum %lX vs module %lX\n", +		pr_debug("Found checksum %lX vs module %lX\n",  		       maybe_relocated(*crc, crc_owner), versions[i].crc);  		goto bad_version;  	} @@ -1834,7 +1875,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)  		case SHN_COMMON:  			/* We compiled with -fno-common.  These are not  			   supposed to happen.  */ -			DEBUGP("Common symbol: %s\n", name); +			pr_debug("Common symbol: %s\n", name);  			printk("%s: please compile with -fno-common\n",  			       mod->name);  			ret = -ENOEXEC; @@ -1842,7 +1883,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)  		case SHN_ABS:  			/* Don't need to do anything */ -			DEBUGP("Absolute symbol: 0x%08lx\n", +			pr_debug("Absolute symbol: 0x%08lx\n",  			       (long)sym[i].st_value);  			break; @@ -1966,7 +2007,7 @@ static void layout_sections(struct module *mod, struct load_info *info)  	for (i = 0; i < info->hdr->e_shnum; i++)  		info->sechdrs[i].sh_entsize = ~0UL; -	DEBUGP("Core section allocation order:\n"); +	pr_debug("Core section allocation order:\n");  	for (m = 0; m < ARRAY_SIZE(masks); ++m) {  		for (i = 0; i < info->hdr->e_shnum; ++i) {  			Elf_Shdr *s = &info->sechdrs[i]; @@ -1978,7 +2019,7 @@ static void layout_sections(struct module *mod, struct load_info *info)  			    || strstarts(sname, ".init"))  				continue;  			s->sh_entsize = get_offset(mod, &mod->core_size, s, i); -			DEBUGP("\t%s\n", name); +			pr_debug("\t%s\n", sname);  		}  		switch (m) {  		case 0: /* executable */ @@ -1995,7 +2036,7 @@ static void layout_sections(struct module *mod, struct load_info *info)  		}  	} -	DEBUGP("Init section allocation order:\n"); +	pr_debug("Init section allocation order:\n");  	for (m = 0; m < ARRAY_SIZE(masks); ++m) {  		for (i = 0; i < info->hdr->e_shnum; ++i) {  			Elf_Shdr *s = &info->sechdrs[i]; @@ -2008,7 +2049,7 @@ static void layout_sections(struct module *mod, struct load_info *info)  				continue;  			s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)  					 | INIT_OFFSET_MASK); -			DEBUGP("\t%s\n", sname); +			pr_debug("\t%s\n", sname);  		}  		switch (m) {  		case 0: /* executable */ @@ -2178,45 +2219,46 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,  	return true;  } +/* + * We only allocate and copy the strings needed by the parts of symtab + * we keep.  This is simple, but has the effect of making multiple + * copies of duplicates.  We could be more sophisticated, see + * linux-kernel thread starting with + * <73defb5e4bca04a6431392cc341112b1@localhost>. + */  static void layout_symtab(struct module *mod, struct load_info *info)  {  	Elf_Shdr *symsect = info->sechdrs + info->index.sym;  	Elf_Shdr *strsect = info->sechdrs + info->index.str;  	const Elf_Sym *src; -	unsigned int i, nsrc, ndst; +	unsigned int i, nsrc, ndst, strtab_size;  	/* Put symbol section at end of init part of module. */  	symsect->sh_flags |= SHF_ALLOC;  	symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect,  					 info->index.sym) | INIT_OFFSET_MASK; -	DEBUGP("\t%s\n", info->secstrings + symsect->sh_name); +	pr_debug("\t%s\n", info->secstrings + symsect->sh_name);  	src = (void *)info->hdr + symsect->sh_offset;  	nsrc = symsect->sh_size / sizeof(*src); -	for (ndst = i = 1; i < nsrc; ++i, ++src) -		if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { -			unsigned int j = src->st_name; -			while (!__test_and_set_bit(j, info->strmap) -			       && info->strtab[j]) -				++j; -			++ndst; +	/* Compute total space required for the core symbols' strtab. */ +	for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) +		if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { +			strtab_size += strlen(&info->strtab[src->st_name]) + 1; +			ndst++;  		}  	/* Append room for core symbols at end of core part. */  	info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); -	mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym); +	info->stroffs = mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym); +	mod->core_size += strtab_size;  	/* Put string table section at end of init part of module. */  	strsect->sh_flags |= SHF_ALLOC;  	strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,  					 info->index.str) | INIT_OFFSET_MASK; -	DEBUGP("\t%s\n", info->secstrings + strsect->sh_name); - -	/* Append room for core symbols' strings at end of core part. */ -	info->stroffs = mod->core_size; -	__set_bit(0, info->strmap); -	mod->core_size += bitmap_weight(info->strmap, strsect->sh_size); +	pr_debug("\t%s\n", info->secstrings + strsect->sh_name);  }  static void add_kallsyms(struct module *mod, const struct load_info *info) @@ -2237,22 +2279,19 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)  		mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);  	mod->core_symtab = dst = mod->module_core + info->symoffs; +	mod->core_strtab = s = mod->module_core + info->stroffs;  	src = mod->symtab;  	*dst = *src; +	*s++ = 0;  	for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {  		if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))  			continue; +  		dst[ndst] = *src; -		dst[ndst].st_name = bitmap_weight(info->strmap, -						  dst[ndst].st_name); -		++ndst; +		dst[ndst++].st_name = s - mod->core_strtab; +		s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;  	}  	mod->core_num_syms = ndst; - -	mod->core_strtab = s = mod->module_core + info->stroffs; -	for (*s = 0, i = 1; i < info->sechdrs[info->index.str].sh_size; ++i) -		if (test_bit(i, info->strmap)) -			*++s = mod->strtab[i];  }  #else  static inline void layout_symtab(struct module *mod, struct load_info *info) @@ -2621,7 +2660,7 @@ static int move_module(struct module *mod, struct load_info *info)  	mod->module_init = ptr;  	/* Transfer each section which specifies SHF_ALLOC */ -	DEBUGP("final section addresses:\n"); +	pr_debug("final section addresses:\n");  	for (i = 0; i < info->hdr->e_shnum; i++) {  		void *dest;  		Elf_Shdr *shdr = &info->sechdrs[i]; @@ -2639,8 +2678,8 @@ static int move_module(struct module *mod, struct load_info *info)  			memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);  		/* Update sh_addr to point to copy in image. */  		shdr->sh_addr = (unsigned long)dest; -		DEBUGP("\t0x%lx %s\n", -		       shdr->sh_addr, info->secstrings + shdr->sh_name); +		pr_debug("\t0x%lx %s\n", +			 (long)shdr->sh_addr, info->secstrings + shdr->sh_name);  	}  	return 0; @@ -2742,27 +2781,18 @@ static struct module *layout_and_allocate(struct load_info *info)  	   this is done generically; there doesn't appear to be any  	   special cases for the architectures. */  	layout_sections(mod, info); - -	info->strmap = kzalloc(BITS_TO_LONGS(info->sechdrs[info->index.str].sh_size) -			 * sizeof(long), GFP_KERNEL); -	if (!info->strmap) { -		err = -ENOMEM; -		goto free_percpu; -	}  	layout_symtab(mod, info);  	/* Allocate and move to the final place */  	err = move_module(mod, info);  	if (err) -		goto free_strmap; +		goto free_percpu;  	/* Module has been copied to its final place now: return it. */  	mod = (void *)info->sechdrs[info->index.mod].sh_addr;  	kmemleak_load_module(mod, info);  	return mod; -free_strmap: -	kfree(info->strmap);  free_percpu:  	percpu_modfree(mod);  out: @@ -2772,7 +2802,6 @@ out:  /* mod is no longer valid after this! */  static void module_deallocate(struct module *mod, struct load_info *info)  { -	kfree(info->strmap);  	percpu_modfree(mod);  	module_free(mod, mod->module_init);  	module_free(mod, mod->module_core); @@ -2811,7 +2840,7 @@ static struct module *load_module(void __user *umod,  	struct module *mod;  	long err; -	DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", +	pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",  	       umod, len, uargs);  	/* Copy in the blobs from userspace, check they are vaguely sane. */ @@ -2902,8 +2931,7 @@ static struct module *load_module(void __user *umod,  	if (err < 0)  		goto unlink; -	/* Get rid of temporary copy and strmap. */ -	kfree(info.strmap); +	/* Get rid of temporary copy. */  	free_copy(&info);  	/* Done! */ @@ -3256,20 +3284,7 @@ static char *module_flags(struct module *mod, char *buf)  	    mod->state == MODULE_STATE_GOING ||  	    mod->state == MODULE_STATE_COMING) {  		buf[bx++] = '('; -		if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE)) -			buf[bx++] = 'P'; -		else if (mod->taints & (1 << TAINT_OOT_MODULE)) -			buf[bx++] = 'O'; -		if (mod->taints & (1 << TAINT_FORCED_MODULE)) -			buf[bx++] = 'F'; -		if (mod->taints & (1 << TAINT_CRAP)) -			buf[bx++] = 'C'; -		/* -		 * TAINT_FORCED_RMMOD: could be added. -		 * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't -		 * apply to modules. -		 */ - +		bx += module_flags_taint(mod, buf + bx);  		/* Show a - for module-is-being-unloaded */  		if (mod->state == MODULE_STATE_GOING)  			buf[bx++] = '-'; | 
