3539 lines · 89.7 KB · C
RawDownload
/* Additional bytes needed by arch in front of individual sections */unsigned int __weak arch_mod_section_prepend(struct module *mod,					     unsigned int section){	/* default implementation just returns zero */	return 0;} /* Update size with this section: return offset. */static long get_offset(struct module *mod, unsigned int *size,		       Elf_Shdr *sechdr, unsigned int section){	long ret; 	*size += arch_mod_section_prepend(mod, section);	ret = ALIGN(*size, sechdr->sh_addralign ?: 1);	*size = ret + sechdr->sh_size;	return ret;} /* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld   might -- code, read-only data, read-write data, small data.  Tally   sizes, and place the offsets into sh_entsize fields: high bit means it   belongs in init. */static void layout_sections(struct module *mod, struct load_info *info){	static unsigned long const masks[][2] = {		/* NOTE: all executable code must be the first section		 * in this array; otherwise modify the text_size		 * finder in the two loops below */		{ SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },		{ SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },		{ SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },		{ ARCH_SHF_SMALL | SHF_ALLOC, 0 }	};	unsigned int m, i; 	for (i = 0; i < info->hdr->e_shnum; i++)		info->sechdrs[i].sh_entsize = ~0UL; 	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];			const char *sname = info->secstrings + s->sh_name; 			if ((s->sh_flags & masks[m][0]) != masks[m][0]			    || (s->sh_flags & masks[m][1])			    || s->sh_entsize != ~0UL			    || strstarts(sname, ".init"))				continue;			s->sh_entsize = get_offset(mod, &mod->core_size, s, i);			pr_debug("\t%s\n", sname);		}		switch (m) {		case 0: /* executable */			mod->core_size = debug_align(mod->core_size);			mod->core_text_size = mod->core_size;			break;		case 1: /* RO: text and ro-data */			mod->core_size = debug_align(mod->core_size);			mod->core_ro_size = mod->core_size;			break;		case 3: /* whole core */			mod->core_size = debug_align(mod->core_size);			break;		}	} 	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];			const char *sname = info->secstrings + s->sh_name; 			if ((s->sh_flags & masks[m][0]) != masks[m][0]			    || (s->sh_flags & masks[m][1])			    || s->sh_entsize != ~0UL			    || !strstarts(sname, ".init"))				continue;			s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)					 | INIT_OFFSET_MASK);			pr_debug("\t%s\n", sname);		}		switch (m) {		case 0: /* executable */			mod->init_size = debug_align(mod->init_size);			mod->init_text_size = mod->init_size;			break;		case 1: /* RO: text and ro-data */			mod->init_size = debug_align(mod->init_size);			mod->init_ro_size = mod->init_size;			break;		case 3: /* whole init */			mod->init_size = debug_align(mod->init_size);			break;		}	}} static void set_license(struct module *mod, const char *license){	if (!license)		license = "unspecified"; 	if (!license_is_gpl_compatible(license)) {		if (!test_taint(TAINT_PROPRIETARY_MODULE))			printk(KERN_WARNING "%s: module license '%s' taints "				"kernel.\n", mod->name, license);		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);	}} /* Parse tag=value strings from .modinfo section */static char *next_string(char *string, unsigned long *secsize){	/* Skip non-zero chars */	while (string[0]) {		string++;		if ((*secsize)-- <= 1)			return NULL;	} 	/* Skip any zero padding. */	while (!string[0]) {		string++;		if ((*secsize)-- <= 1)			return NULL;	}	return string;} static char *get_modinfo(struct load_info *info, const char *tag){	char *p;	unsigned int taglen = strlen(tag);	Elf_Shdr *infosec = &info->sechdrs[info->index.info];	unsigned long size = infosec->sh_size; 	for (p = (char *)infosec->sh_addr; p; p = next_string(p, &size)) {		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')			return p + taglen + 1;	}	return NULL;} static void setup_modinfo(struct module *mod, struct load_info *info){	struct module_attribute *attr;	int i; 	for (i = 0; (attr = modinfo_attrs[i]); i++) {		if (attr->setup)			attr->setup(mod, get_modinfo(info, attr->attr.name));	}} static void free_modinfo(struct module *mod){	struct module_attribute *attr;	int i; 	for (i = 0; (attr = modinfo_attrs[i]); i++) {		if (attr->free)			attr->free(mod);	}} #ifdef CONFIG_KALLSYMS /* lookup symbol in given range of kernel_symbols */static const struct kernel_symbol *lookup_symbol(const char *name,	const struct kernel_symbol *start,	const struct kernel_symbol *stop){	return bsearch(name, start, stop - start,			sizeof(struct kernel_symbol), cmp_name);} static int is_exported(const char *name, unsigned long value,		       const struct module *mod){	const struct kernel_symbol *ks;	if (!mod)		ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);	else		ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);	return ks != NULL && ks->value == value;} /* As per nm */static char elf_type(const Elf_Sym *sym, const struct load_info *info){	const Elf_Shdr *sechdrs = info->sechdrs; 	if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)			return 'v';		else			return 'w';	}	if (sym->st_shndx == SHN_UNDEF)		return 'U';	if (sym->st_shndx == SHN_ABS)		return 'a';	if (sym->st_shndx >= SHN_LORESERVE)		return '?';	if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR)		return 't';	if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC	    && sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) {		if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE))			return 'r';		else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)			return 'g';		else			return 'd';	}	if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {		if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)			return 's';		else			return 'b';	}	if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name,		      ".debug")) {		return 'n';	}	return '?';} static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,                           unsigned int shnum){	const Elf_Shdr *sec; 	if (src->st_shndx == SHN_UNDEF	    || src->st_shndx >= shnum	    || !src->st_name)		return false; 	sec = sechdrs + src->st_shndx;	if (!(sec->sh_flags & SHF_ALLOC)#ifndef CONFIG_KALLSYMS_ALL	    || !(sec->sh_flags & SHF_EXECINSTR)#endif	    || (sec->sh_entsize & INIT_OFFSET_MASK))		return false; 	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, 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;	pr_debug("\t%s\n", info->secstrings + symsect->sh_name); 	src = (void *)info->hdr + symsect->sh_offset;	nsrc = symsect->sh_size / sizeof(*src); 	/* 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);	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;	pr_debug("\t%s\n", info->secstrings + strsect->sh_name);} static void add_kallsyms(struct module *mod, const struct load_info *info){	unsigned int i, ndst;	const Elf_Sym *src;	Elf_Sym *dst;	char *s;	Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; 	mod->symtab = (void *)symsec->sh_addr;	mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);	/* Make sure we get permanent strtab: don't use info->strtab. */	mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr; 	/* Set types up while we still have access to sections. */	for (i = 0; i < mod->num_symtab; i++)		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 = s - mod->core_strtab;		s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;	}	mod->core_num_syms = ndst;}#elsestatic inline void layout_symtab(struct module *mod, struct load_info *info){} static void add_kallsyms(struct module *mod, const struct load_info *info){}#endif /* CONFIG_KALLSYMS */ static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num){	if (!debug)		return;#ifdef CONFIG_DYNAMIC_DEBUG	if (ddebug_add_module(debug, num, debug->modname))		printk(KERN_ERR "dynamic debug error adding module: %s\n",					debug->modname);#endif} static void dynamic_debug_remove(struct _ddebug *debug){	if (debug)		ddebug_remove_module(debug->modname);} void * __weak module_alloc(unsigned long size){	return size == 0 ? NULL : vmalloc_exec(size);} static void *module_alloc_update_bounds(unsigned long size){	void *ret = module_alloc(size); 	if (ret) {		mutex_lock(&module_mutex);		/* Update module bounds. */		if ((unsigned long)ret < module_addr_min)			module_addr_min = (unsigned long)ret;		if ((unsigned long)ret + size > module_addr_max)			module_addr_max = (unsigned long)ret + size;		mutex_unlock(&module_mutex);	}	return ret;} #ifdef CONFIG_DEBUG_KMEMLEAKstatic void kmemleak_load_module(const struct module *mod,				 const struct load_info *info){	unsigned int i; 	/* only scan the sections containing data */	kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL); 	for (i = 1; i < info->hdr->e_shnum; i++) {		const char *name = info->secstrings + info->sechdrs[i].sh_name;		if (!(info->sechdrs[i].sh_flags & SHF_ALLOC))			continue;		if (!strstarts(name, ".data") && !strstarts(name, ".bss"))			continue; 		kmemleak_scan_area((void *)info->sechdrs[i].sh_addr,				   info->sechdrs[i].sh_size, GFP_KERNEL);	}}#elsestatic inline void kmemleak_load_module(const struct module *mod,					const struct load_info *info){}#endif /* Sets info->hdr and info->len. */static int copy_and_check(struct load_info *info,			  const void __user *umod, unsigned long len,			  const char __user *uargs){	int err;	Elf_Ehdr *hdr; 	if (len < sizeof(*hdr))		return -ENOEXEC; 	/* Suck in entire file: we'll want most of it. */	if ((hdr = vmalloc(len)) == NULL)		return -ENOMEM; 	if (copy_from_user(hdr, umod, len) != 0) {		err = -EFAULT;		goto free_hdr;	} 	/* Sanity checks against insmoding binaries or wrong arch,	   weird elf version */	if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0	    || hdr->e_type != ET_REL	    || !elf_check_arch(hdr)	    || hdr->e_shentsize != sizeof(Elf_Shdr)) {		err = -ENOEXEC;		goto free_hdr;	} 	if (hdr->e_shoff >= len ||	    hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) {		err = -ENOEXEC;		goto free_hdr;	} 	info->hdr = hdr;	info->len = len;	return 0; free_hdr:	vfree(hdr);	return err;} static void free_copy(struct load_info *info){	vfree(info->hdr);} static int rewrite_section_headers(struct load_info *info){	unsigned int i; 	/* This should always be true, but let's be sure. */	info->sechdrs[0].sh_addr = 0; 	for (i = 1; i < info->hdr->e_shnum; i++) {		Elf_Shdr *shdr = &info->sechdrs[i];		if (shdr->sh_type != SHT_NOBITS		    && info->len < shdr->sh_offset + shdr->sh_size) {			printk(KERN_ERR "Module len %lu truncated\n",			       info->len);			return -ENOEXEC;		} 		/* Mark all sections sh_addr with their address in the		   temporary image. */		shdr->sh_addr = (size_t)info->hdr + shdr->sh_offset; #ifndef CONFIG_MODULE_UNLOAD		/* Don't load .exit sections */		if (strstarts(info->secstrings+shdr->sh_name, ".exit"))			shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;#endif	} 	/* Track but don't keep modinfo and version sections. */	info->index.vers = find_sec(info, "__versions");	info->index.info = find_sec(info, ".modinfo");	info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;	info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;	return 0;} /* * Set up our basic convenience variables (pointers to section headers, * search for module section index etc), and do some basic section * verification. * * Return the temporary module pointer (we'll replace it with the final * one when we move the module sections around). */static struct module *setup_load_info(struct load_info *info){	unsigned int i;	int err;	struct module *mod; 

Lines 2001–2500 of 3539. Previous lines