4590 lines · 117.2 KB · C
RawDownload
			    || !module_init_section(sname))				continue;			s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i)					 | INIT_OFFSET_MASK);			pr_debug("\t%s\n", sname);		}		switch (m) {		case 0: /* executable */			mod->init_layout.size = debug_align(mod->init_layout.size);			mod->init_layout.text_size = mod->init_layout.size;			break;		case 1: /* RO: text and ro-data */			mod->init_layout.size = debug_align(mod->init_layout.size);			mod->init_layout.ro_size = mod->init_layout.size;			break;		case 2:			/*			 * RO after init doesn't apply to init_layout (only			 * core_layout), so it just takes the value of ro_size.			 */			mod->init_layout.ro_after_init_size = mod->init_layout.ro_size;			break;		case 4: /* whole init */			mod->init_layout.size = debug_align(mod->init_layout.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))			pr_warn("%s: module license '%s' taints kernel.\n",				mod->name, license);		add_taint_module(mod, TAINT_PROPRIETARY_MODULE,				 LOCKDEP_NOW_UNRELIABLE);	}} /* 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_next_modinfo(const struct load_info *info, const char *tag,			      char *prev){	char *p;	unsigned int taglen = strlen(tag);	Elf_Shdr *infosec = &info->sechdrs[info->index.info];	unsigned long size = infosec->sh_size; 	/*	 * get_modinfo() calls made before rewrite_section_headers()	 * must use sh_offset, as sh_addr isn't set!	 */	char *modinfo = (char *)info->hdr + infosec->sh_offset; 	if (prev) {		size -= prev - modinfo;		modinfo = next_string(prev, &size);	} 	for (p = modinfo; p; p = next_string(p, &size)) {		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')			return p + taglen + 1;	}	return NULL;} static char *get_modinfo(const struct load_info *info, const char *tag){	return get_next_modinfo(info, tag, 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 exported symbol in given range of kernel_symbols */static const struct kernel_symbol *lookup_exported_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_exported_symbol(name, __start___ksymtab, __stop___ksymtab);	else		ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms); 	return ks != NULL && kernel_symbol_value(ks) == 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 || sym->st_shndx == info->index.pcpu)		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, unsigned int pcpundx){	const Elf_Shdr *sec; 	if (src->st_shndx == SHN_UNDEF	    || src->st_shndx >= shnum	    || !src->st_name)		return false; #ifdef CONFIG_KALLSYMS_ALL	if (src->st_shndx == pcpundx)		return true;#endif 	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 = 0; 	/* Put symbol section at end of init part of module. */	symsect->sh_flags |= SHF_ALLOC;	symsect->sh_entsize = get_offset(mod, &mod->init_layout.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 = 0; i < nsrc; i++) {		if (i == 0 || is_livepatch_module(mod) ||		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,				   info->index.pcpu)) {			strtab_size += strlen(&info->strtab[src[i].st_name])+1;			ndst++;		}	} 	/* Append room for core symbols at end of core part. */	info->symoffs = ALIGN(mod->core_layout.size, symsect->sh_addralign ?: 1);	info->stroffs = mod->core_layout.size = info->symoffs + ndst * sizeof(Elf_Sym);	mod->core_layout.size += strtab_size;	info->core_typeoffs = mod->core_layout.size;	mod->core_layout.size += ndst * sizeof(char);	mod->core_layout.size = debug_align(mod->core_layout.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_layout.size, strsect,					 info->index.str) | INIT_OFFSET_MASK;	pr_debug("\t%s\n", info->secstrings + strsect->sh_name); 	/* We'll tack temporary mod_kallsyms on the end. */	mod->init_layout.size = ALIGN(mod->init_layout.size,				      __alignof__(struct mod_kallsyms));	info->mod_kallsyms_init_off = mod->init_layout.size;	mod->init_layout.size += sizeof(struct mod_kallsyms);	info->init_typeoffs = mod->init_layout.size;	mod->init_layout.size += nsrc * sizeof(char);	mod->init_layout.size = debug_align(mod->init_layout.size);} /* * We use the full symtab and strtab which layout_symtab arranged to * be appended to the init section.  Later we switch to the cut-down * core-only ones. */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]; 	/* Set up to point into init section. */	mod->kallsyms = mod->init_layout.base + info->mod_kallsyms_init_off; 	mod->kallsyms->symtab = (void *)symsec->sh_addr;	mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);	/* Make sure we get permanent strtab: don't use info->strtab. */	mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;	mod->kallsyms->typetab = mod->init_layout.base + info->init_typeoffs; 	/*	 * Now populate the cut down core kallsyms for after init	 * and set types up while we still have access to sections.	 */	mod->core_kallsyms.symtab = dst = mod->core_layout.base + info->symoffs;	mod->core_kallsyms.strtab = s = mod->core_layout.base + info->stroffs;	mod->core_kallsyms.typetab = mod->core_layout.base + info->core_typeoffs;	src = mod->kallsyms->symtab;	for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {		mod->kallsyms->typetab[i] = elf_type(src + i, info);		if (i == 0 || is_livepatch_module(mod) ||		    is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,				   info->index.pcpu)) {			mod->core_kallsyms.typetab[ndst] =			    mod->kallsyms->typetab[i];			dst[ndst] = src[i];			dst[ndst++].st_name = s - mod->core_kallsyms.strtab;			s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],				     KSYM_NAME_LEN) + 1;		}	}	mod->core_kallsyms.num_symtab = 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 module *mod, struct _ddebug *debug, unsigned int num){	if (!debug)		return;	ddebug_add_module(debug, num, mod->name);} static void dynamic_debug_remove(struct module *mod, struct _ddebug *debug){	if (debug)		ddebug_remove_module(mod->name);} void * __weak module_alloc(unsigned long size){	return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,			GFP_KERNEL, PAGE_KERNEL_EXEC, VM_FLUSH_RESET_PERMS,			NUMA_NO_NODE, __builtin_return_address(0));} bool __weak module_init_section(const char *name){	return strstarts(name, ".init");} bool __weak module_exit_section(const char *name){	return strstarts(name, ".exit");} #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++) {		/* Scan all writable sections that's not executable */		if (!(info->sechdrs[i].sh_flags & SHF_ALLOC) ||		    !(info->sechdrs[i].sh_flags & SHF_WRITE) ||		    (info->sechdrs[i].sh_flags & SHF_EXECINSTR))			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 #ifdef CONFIG_MODULE_SIGstatic int module_sig_check(struct load_info *info, int flags){	int err = -ENODATA;	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;	const char *reason;	const void *mod = info->hdr; 	/*	 * Require flags == 0, as a module with version information	 * removed is no longer the module that was signed	 */	if (flags == 0 &&	    info->len > markerlen &&	    memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {		/* We truncate the module to discard the signature */		info->len -= markerlen;		err = mod_verify_sig(mod, info);	} 	switch (err) {	case 0:		info->sig_ok = true;		return 0; 		/* We don't permit modules to be loaded into trusted kernels		 * without a valid signature on them, but if we're not		 * enforcing, certain errors are non-fatal.		 */	case -ENODATA:		reason = "Loading of unsigned module";		goto decide;	case -ENOPKG:		reason = "Loading of module with unsupported crypto";		goto decide;	case -ENOKEY:		reason = "Loading of module with unavailable key";	decide:		if (is_module_sig_enforced()) {			pr_notice("%s: %s is rejected\n", info->name, reason);			return -EKEYREJECTED;		} 		return security_locked_down(LOCKDOWN_MODULE_SIGNATURE); 		/* All other errors are fatal, including nomem, unparseable		 * signatures and signature check failures - even if signatures		 * aren't required.		 */	default:		return err;	}}#else /* !CONFIG_MODULE_SIG */static int module_sig_check(struct load_info *info, int flags){	return 0;}#endif /* !CONFIG_MODULE_SIG */ /* Sanity checks against invalid binaries, wrong arch, weird elf version. */static int elf_header_check(struct load_info *info){	if (info->len < sizeof(*(info->hdr)))		return -ENOEXEC; 	if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0	    || info->hdr->e_type != ET_REL	    || !elf_check_arch(info->hdr)	    || info->hdr->e_shentsize != sizeof(Elf_Shdr))		return -ENOEXEC; 	if (info->hdr->e_shoff >= info->len	    || (info->hdr->e_shnum * sizeof(Elf_Shdr) >		info->len - info->hdr->e_shoff))		return -ENOEXEC; 	return 0;} #define COPY_CHUNK_SIZE (16*PAGE_SIZE) static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned long len){	do {		unsigned long n = min(len, COPY_CHUNK_SIZE); 		if (copy_from_user(dst, usrc, n) != 0)			return -EFAULT;		cond_resched();		dst += n;		usrc += n;		len -= n;	} while (len);	return 0;} #ifdef CONFIG_LIVEPATCHstatic int check_modinfo_livepatch(struct module *mod, struct load_info *info){	if (get_modinfo(info, "livepatch")) {		mod->klp = true;		add_taint_module(mod, TAINT_LIVEPATCH, LOCKDEP_STILL_OK);		pr_notice_once("%s: tainting kernel with TAINT_LIVEPATCH\n",			       mod->name);	} 	return 0;}#else /* !CONFIG_LIVEPATCH */static int check_modinfo_livepatch(struct module *mod, struct load_info *info){	if (get_modinfo(info, "livepatch")) {		pr_err("%s: module is marked as livepatch module, but livepatch support is disabled",		       mod->name);		return -ENOEXEC;	} 	return 0;}#endif /* CONFIG_LIVEPATCH */ static void check_modinfo_retpoline(struct module *mod, struct load_info *info){	if (retpoline_module_ok(get_modinfo(info, "retpoline")))		return;

Lines 2501–3000 of 4590. Previous lines