3539 lines · 89.7 KB · C
RawDownload
	/* Set up the convenience variables */	info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;	info->secstrings = (void *)info->hdr		+ info->sechdrs[info->hdr->e_shstrndx].sh_offset; 	err = rewrite_section_headers(info);	if (err)		return ERR_PTR(err); 	/* Find internal symbols and strings. */	for (i = 1; i < info->hdr->e_shnum; i++) {		if (info->sechdrs[i].sh_type == SHT_SYMTAB) {			info->index.sym = i;			info->index.str = info->sechdrs[i].sh_link;			info->strtab = (char *)info->hdr				+ info->sechdrs[info->index.str].sh_offset;			break;		}	} 	info->index.mod = find_sec(info, ".gnu.linkonce.this_module");	if (!info->index.mod) {		printk(KERN_WARNING "No module found in object\n");		return ERR_PTR(-ENOEXEC);	}	/* This is temporary: point mod into copy of data. */	mod = (void *)info->sechdrs[info->index.mod].sh_addr; 	if (info->index.sym == 0) {		printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",		       mod->name);		return ERR_PTR(-ENOEXEC);	} 	info->index.pcpu = find_pcpusec(info); 	/* Check module struct version now, before we try to use module. */	if (!check_modstruct_version(info->sechdrs, info->index.vers, mod))		return ERR_PTR(-ENOEXEC); 	return mod;} static int check_modinfo(struct module *mod, struct load_info *info){	const char *modmagic = get_modinfo(info, "vermagic");	int err; 	/* This is allowed: modprobe --force will invalidate it. */	if (!modmagic) {		err = try_to_force_load(mod, "bad vermagic");		if (err)			return err;	} else if (!same_magic(modmagic, vermagic, info->index.vers)) {		printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",		       mod->name, modmagic, vermagic);		return -ENOEXEC;	} 	if (!get_modinfo(info, "intree"))		add_taint_module(mod, TAINT_OOT_MODULE); 	if (get_modinfo(info, "staging")) {		add_taint_module(mod, TAINT_CRAP);		printk(KERN_WARNING "%s: module is from the staging directory,"		       " the quality is unknown, you have been warned.\n",		       mod->name);	} 	/* Set up license info based on the info section */	set_license(mod, get_modinfo(info, "license")); 	return 0;} static void find_module_sections(struct module *mod, struct load_info *info){	mod->kp = section_objs(info, "__param",			       sizeof(*mod->kp), &mod->num_kp);	mod->syms = section_objs(info, "__ksymtab",				 sizeof(*mod->syms), &mod->num_syms);	mod->crcs = section_addr(info, "__kcrctab");	mod->gpl_syms = section_objs(info, "__ksymtab_gpl",				     sizeof(*mod->gpl_syms),				     &mod->num_gpl_syms);	mod->gpl_crcs = section_addr(info, "__kcrctab_gpl");	mod->gpl_future_syms = section_objs(info,					    "__ksymtab_gpl_future",					    sizeof(*mod->gpl_future_syms),					    &mod->num_gpl_future_syms);	mod->gpl_future_crcs = section_addr(info, "__kcrctab_gpl_future"); #ifdef CONFIG_UNUSED_SYMBOLS	mod->unused_syms = section_objs(info, "__ksymtab_unused",					sizeof(*mod->unused_syms),					&mod->num_unused_syms);	mod->unused_crcs = section_addr(info, "__kcrctab_unused");	mod->unused_gpl_syms = section_objs(info, "__ksymtab_unused_gpl",					    sizeof(*mod->unused_gpl_syms),					    &mod->num_unused_gpl_syms);	mod->unused_gpl_crcs = section_addr(info, "__kcrctab_unused_gpl");#endif#ifdef CONFIG_CONSTRUCTORS	mod->ctors = section_objs(info, ".ctors",				  sizeof(*mod->ctors), &mod->num_ctors);#endif #ifdef CONFIG_TRACEPOINTS	mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",					     sizeof(*mod->tracepoints_ptrs),					     &mod->num_tracepoints);#endif#ifdef HAVE_JUMP_LABEL	mod->jump_entries = section_objs(info, "__jump_table",					sizeof(*mod->jump_entries),					&mod->num_jump_entries);#endif#ifdef CONFIG_EVENT_TRACING	mod->trace_events = section_objs(info, "_ftrace_events",					 sizeof(*mod->trace_events),					 &mod->num_trace_events);	/*	 * This section contains pointers to allocated objects in the trace	 * code and not scanning it leads to false positives.	 */	kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) *			   mod->num_trace_events, GFP_KERNEL);#endif#ifdef CONFIG_TRACING	mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt",					 sizeof(*mod->trace_bprintk_fmt_start),					 &mod->num_trace_bprintk_fmt);	/*	 * This section contains pointers to allocated objects in the trace	 * code and not scanning it leads to false positives.	 */	kmemleak_scan_area(mod->trace_bprintk_fmt_start,			   sizeof(*mod->trace_bprintk_fmt_start) *			   mod->num_trace_bprintk_fmt, GFP_KERNEL);#endif#ifdef CONFIG_FTRACE_MCOUNT_RECORD	/* sechdrs[0].sh_size is always zero */	mod->ftrace_callsites = section_objs(info, "__mcount_loc",					     sizeof(*mod->ftrace_callsites),					     &mod->num_ftrace_callsites);#endif 	mod->extable = section_objs(info, "__ex_table",				    sizeof(*mod->extable), &mod->num_exentries); 	if (section_addr(info, "__obsparm"))		printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",		       mod->name); 	info->debug = section_objs(info, "__verbose",				   sizeof(*info->debug), &info->num_debug);} static int move_module(struct module *mod, struct load_info *info){	int i;	void *ptr; 	/* Do the allocs. */	ptr = module_alloc_update_bounds(mod->core_size);	/*	 * The pointer to this block is stored in the module structure	 * which is inside the block. Just mark it as not being a	 * leak.	 */	kmemleak_not_leak(ptr);	if (!ptr)		return -ENOMEM; 	memset(ptr, 0, mod->core_size);	mod->module_core = ptr; 	ptr = module_alloc_update_bounds(mod->init_size);	/*	 * The pointer to this block is stored in the module structure	 * which is inside the block. This block doesn't need to be	 * scanned as it contains data and code that will be freed	 * after the module is initialized.	 */	kmemleak_ignore(ptr);	if (!ptr && mod->init_size) {		module_free(mod, mod->module_core);		return -ENOMEM;	}	memset(ptr, 0, mod->init_size);	mod->module_init = ptr; 	/* Transfer each section which specifies SHF_ALLOC */	pr_debug("final section addresses:\n");	for (i = 0; i < info->hdr->e_shnum; i++) {		void *dest;		Elf_Shdr *shdr = &info->sechdrs[i]; 		if (!(shdr->sh_flags & SHF_ALLOC))			continue; 		if (shdr->sh_entsize & INIT_OFFSET_MASK)			dest = mod->module_init				+ (shdr->sh_entsize & ~INIT_OFFSET_MASK);		else			dest = mod->module_core + shdr->sh_entsize; 		if (shdr->sh_type != SHT_NOBITS)			memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);		/* Update sh_addr to point to copy in image. */		shdr->sh_addr = (unsigned long)dest;		pr_debug("\t0x%lx %s\n",			 (long)shdr->sh_addr, info->secstrings + shdr->sh_name);	} 	return 0;} static int check_module_license_and_versions(struct module *mod){	/*	 * ndiswrapper is under GPL by itself, but loads proprietary modules.	 * Don't use add_taint_module(), as it would prevent ndiswrapper from	 * using GPL-only symbols it needs.	 */	if (strcmp(mod->name, "ndiswrapper") == 0)		add_taint(TAINT_PROPRIETARY_MODULE); 	/* driverloader was caught wrongly pretending to be under GPL */	if (strcmp(mod->name, "driverloader") == 0)		add_taint_module(mod, TAINT_PROPRIETARY_MODULE); #ifdef CONFIG_MODVERSIONS	if ((mod->num_syms && !mod->crcs)	    || (mod->num_gpl_syms && !mod->gpl_crcs)	    || (mod->num_gpl_future_syms && !mod->gpl_future_crcs)#ifdef CONFIG_UNUSED_SYMBOLS	    || (mod->num_unused_syms && !mod->unused_crcs)	    || (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)#endif		) {		return try_to_force_load(mod,					 "no versions for exported symbols");	}#endif	return 0;} static void flush_module_icache(const struct module *mod){	mm_segment_t old_fs; 	/* flush the icache in correct context */	old_fs = get_fs();	set_fs(KERNEL_DS); 	/*	 * Flush the instruction cache, since we've played with text.	 * Do it before processing of module parameters, so the module	 * can provide parameter accessor functions of its own.	 */	if (mod->module_init)		flush_icache_range((unsigned long)mod->module_init,				   (unsigned long)mod->module_init				   + mod->init_size);	flush_icache_range((unsigned long)mod->module_core,			   (unsigned long)mod->module_core + mod->core_size); 	set_fs(old_fs);} int __weak module_frob_arch_sections(Elf_Ehdr *hdr,				     Elf_Shdr *sechdrs,				     char *secstrings,				     struct module *mod){	return 0;} static struct module *layout_and_allocate(struct load_info *info){	/* Module within temporary copy. */	struct module *mod;	Elf_Shdr *pcpusec;	int err; 	mod = setup_load_info(info);	if (IS_ERR(mod))		return mod; 	err = check_modinfo(mod, info);	if (err)		return ERR_PTR(err); 	/* Allow arches to frob section contents and sizes.  */	err = module_frob_arch_sections(info->hdr, info->sechdrs,					info->secstrings, mod);	if (err < 0)		goto out; 	pcpusec = &info->sechdrs[info->index.pcpu];	if (pcpusec->sh_size) {		/* We have a special allocation for this section. */		err = percpu_modalloc(mod,				      pcpusec->sh_size, pcpusec->sh_addralign);		if (err)			goto out;		pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC;	} 	/* Determine total sizes, and put offsets in sh_entsize.  For now	   this is done generically; there doesn't appear to be any	   special cases for the architectures. */	layout_sections(mod, info);	layout_symtab(mod, info); 	/* Allocate and move to the final place */	err = move_module(mod, info);	if (err)		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_percpu:	percpu_modfree(mod);out:	return ERR_PTR(err);} /* mod is no longer valid after this! */static void module_deallocate(struct module *mod, struct load_info *info){	percpu_modfree(mod);	module_free(mod, mod->module_init);	module_free(mod, mod->module_core);} int __weak module_finalize(const Elf_Ehdr *hdr,			   const Elf_Shdr *sechdrs,			   struct module *me){	return 0;} static int post_relocation(struct module *mod, const struct load_info *info){	/* Sort exception table now relocations are done. */	sort_extable(mod->extable, mod->extable + mod->num_exentries); 	/* Copy relocated percpu area over. */	percpu_modcopy(mod, (void *)info->sechdrs[info->index.pcpu].sh_addr,		       info->sechdrs[info->index.pcpu].sh_size); 	/* Setup kallsyms-specific fields. */	add_kallsyms(mod, info); 	/* Arch-specific module finalizing. */	return module_finalize(info->hdr, info->sechdrs, mod);} /* Allocate and load the module: note that size of section 0 is always   zero, and we rely on this for optional sections. */static struct module *load_module(void __user *umod,				  unsigned long len,				  const char __user *uargs){	struct load_info info = { NULL, };	struct module *mod;	long err; 	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. */	err = copy_and_check(&info, umod, len, uargs);	if (err)		return ERR_PTR(err); 	/* Figure out module layout, and allocate all the memory. */	mod = layout_and_allocate(&info);	if (IS_ERR(mod)) {		err = PTR_ERR(mod);		goto free_copy;	} 	/* Now module is in final location, initialize linked lists, etc. */	err = module_unload_init(mod);	if (err)		goto free_module; 	/* Now we've got everything in the final locations, we can	 * find optional sections. */	find_module_sections(mod, &info); 	err = check_module_license_and_versions(mod);	if (err)		goto free_unload; 	/* Set up MODINFO_ATTR fields */	setup_modinfo(mod, &info); 	/* Fix up syms, so that st_value is a pointer to location. */	err = simplify_symbols(mod, &info);	if (err < 0)		goto free_modinfo; 	err = apply_relocations(mod, &info);	if (err < 0)		goto free_modinfo; 	err = post_relocation(mod, &info);	if (err < 0)		goto free_modinfo; 	flush_module_icache(mod); 	/* Now copy in args */	mod->args = strndup_user(uargs, ~0UL >> 1);	if (IS_ERR(mod->args)) {		err = PTR_ERR(mod->args);		goto free_arch_cleanup;	} 	/* Mark state as coming so strong_try_module_get() ignores us. */	mod->state = MODULE_STATE_COMING; 	/* Now sew it into the lists so we can get lockdep and oops	 * info during argument parsing.  No one should access us, since	 * strong_try_module_get() will fail.	 * lockdep/oops can run asynchronous, so use the RCU list insertion	 * function to insert in a way safe to concurrent readers.	 * The mutex protects against concurrent writers.	 */	mutex_lock(&module_mutex);	if (find_module(mod->name)) {		err = -EEXIST;		goto unlock;	} 	/* This has to be done once we're sure module name is unique. */	dynamic_debug_setup(info.debug, info.num_debug); 	/* Find duplicate symbols */	err = verify_export_symbols(mod);	if (err < 0)		goto ddebug; 	module_bug_finalize(info.hdr, info.sechdrs, mod);	list_add_rcu(&mod->list, &modules);	mutex_unlock(&module_mutex); 	/* Module is ready to execute: parsing args may do that. */	err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,			 -32768, 32767, &ddebug_dyndbg_module_param_cb);	if (err < 0)		goto unlink; 	/* Link in to syfs. */	err = mod_sysfs_setup(mod, &info, mod->kp, mod->num_kp);	if (err < 0)		goto unlink; 	/* Get rid of temporary copy. */	free_copy(&info); 	/* Done! */	trace_module_load(mod);	return mod;  unlink:	mutex_lock(&module_mutex);	/* Unlink carefully: kallsyms could be walking list. */	list_del_rcu(&mod->list);	module_bug_cleanup(mod);  ddebug:	dynamic_debug_remove(info.debug); unlock:	mutex_unlock(&module_mutex);	synchronize_sched();	kfree(mod->args); free_arch_cleanup:	module_arch_cleanup(mod); free_modinfo:	free_modinfo(mod); free_unload:	module_unload_free(mod); free_module:	module_deallocate(mod, &info); free_copy:	free_copy(&info);	return ERR_PTR(err);} /* Call module constructors. */static void do_mod_ctors(struct module *mod){

Lines 2501–3000 of 3539. Previous lines