⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 (strncmp(secstrings + sechdrs[sym->st_shndx].sh_name,		    ".debug", strlen(".debug")) == 0)		return 'n';	return '?';}static void add_kallsyms(struct module *mod,			 Elf_Shdr *sechdrs,			 unsigned int symindex,			 unsigned int strindex,			 const char *secstrings){	unsigned int i;	mod->symtab = (void *)sechdrs[symindex].sh_addr;	mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);	mod->strtab = (void *)sechdrs[strindex].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], sechdrs, secstrings, mod);}#elsestatic inline void add_kallsyms(struct module *mod,				Elf_Shdr *sechdrs,				unsigned int symindex,				unsigned int strindex,				const char *secstrings){}#endif /* CONFIG_KALLSYMS *//* 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){	Elf_Ehdr *hdr;	Elf_Shdr *sechdrs;	char *secstrings, *args, *modmagic, *strtab = NULL;	unsigned int i;	unsigned int symindex = 0;	unsigned int strindex = 0;	unsigned int setupindex;	unsigned int exindex;	unsigned int exportindex;	unsigned int modindex;	unsigned int obsparmindex;	unsigned int infoindex;	unsigned int gplindex;	unsigned int crcindex;	unsigned int gplcrcindex;	unsigned int versindex;	unsigned int pcpuindex;	unsigned int gplfutureindex;	unsigned int gplfuturecrcindex;	unsigned int unwindex = 0;	unsigned int unusedindex;	unsigned int unusedcrcindex;	unsigned int unusedgplindex;	unsigned int unusedgplcrcindex;	struct module *mod;	long err = 0;	void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */	struct exception_table_entry *extable;	mm_segment_t old_fs;	DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",	       umod, len, uargs);	if (len < sizeof(*hdr))		return ERR_PTR(-ENOEXEC);	/* Suck in entire file: we'll want most of it. */	/* vmalloc barfs on "unusual" numbers.  Check here */	if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)		return ERR_PTR(-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, 4) != 0	    || hdr->e_type != ET_REL	    || !elf_check_arch(hdr)	    || hdr->e_shentsize != sizeof(*sechdrs)) {		err = -ENOEXEC;		goto free_hdr;	}	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr))		goto truncated;	/* Convenience variables */	sechdrs = (void *)hdr + hdr->e_shoff;	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;	sechdrs[0].sh_addr = 0;	for (i = 1; i < hdr->e_shnum; i++) {		if (sechdrs[i].sh_type != SHT_NOBITS		    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size)			goto truncated;		/* Mark all sections sh_addr with their address in the		   temporary image. */		sechdrs[i].sh_addr = (size_t)hdr + sechdrs[i].sh_offset;		/* Internal symbols and strings. */		if (sechdrs[i].sh_type == SHT_SYMTAB) {			symindex = i;			strindex = sechdrs[i].sh_link;			strtab = (char *)hdr + sechdrs[strindex].sh_offset;		}#ifndef CONFIG_MODULE_UNLOAD		/* Don't load .exit sections */		if (strncmp(secstrings+sechdrs[i].sh_name, ".exit", 5) == 0)			sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;#endif	}	modindex = find_sec(hdr, sechdrs, secstrings,			    ".gnu.linkonce.this_module");	if (!modindex) {		printk(KERN_WARNING "No module found in object\n");		err = -ENOEXEC;		goto free_hdr;	}	mod = (void *)sechdrs[modindex].sh_addr;	if (symindex == 0) {		printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",		       mod->name);		err = -ENOEXEC;		goto free_hdr;	}	/* Optional sections */	exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");	gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");	gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");	unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");	unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");	crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");	gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");	gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");	unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");	unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");	setupindex = find_sec(hdr, sechdrs, secstrings, "__param");	exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");	obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");	versindex = find_sec(hdr, sechdrs, secstrings, "__versions");	infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");	pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);#ifdef ARCH_UNWIND_SECTION_NAME	unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME);#endif	/* Don't keep modinfo section */	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;#ifdef CONFIG_KALLSYMS	/* Keep symbol and string tables for decoding later. */	sechdrs[symindex].sh_flags |= SHF_ALLOC;	sechdrs[strindex].sh_flags |= SHF_ALLOC;#endif	if (unwindex)		sechdrs[unwindex].sh_flags |= SHF_ALLOC;	/* Check module struct version now, before we try to use module. */	if (!check_modstruct_version(sechdrs, versindex, mod)) {		err = -ENOEXEC;		goto free_hdr;	}	modmagic = get_modinfo(sechdrs, infoindex, "vermagic");	/* This is allowed: modprobe --force will invalidate it. */	if (!modmagic) {		add_taint_module(mod, TAINT_FORCED_MODULE);		printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",		       mod->name);	} else if (!same_magic(modmagic, vermagic)) {		printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",		       mod->name, modmagic, vermagic);		err = -ENOEXEC;		goto free_hdr;	}	/* Now copy in args */	args = strndup_user(uargs, ~0UL >> 1);	if (IS_ERR(args)) {		err = PTR_ERR(args);		goto free_hdr;	}	if (find_module(mod->name)) {		err = -EEXIST;		goto free_mod;	}	mod->state = MODULE_STATE_COMING;	/* Allow arches to frob section contents and sizes.  */	err = module_frob_arch_sections(hdr, sechdrs, secstrings, mod);	if (err < 0)		goto free_mod;	if (pcpuindex) {		/* We have a special allocation for this section. */		percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size,					 sechdrs[pcpuindex].sh_addralign,					 mod->name);		if (!percpu) {			err = -ENOMEM;			goto free_mod;		}		sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;		mod->percpu = percpu;	}	/* 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, hdr, sechdrs, secstrings);	/* Do the allocs. */	ptr = module_alloc(mod->core_size);	if (!ptr) {		err = -ENOMEM;		goto free_percpu;	}	memset(ptr, 0, mod->core_size);	mod->module_core = ptr;	ptr = module_alloc(mod->init_size);	if (!ptr && mod->init_size) {		err = -ENOMEM;		goto free_core;	}	memset(ptr, 0, mod->init_size);	mod->module_init = ptr;	/* Transfer each section which specifies SHF_ALLOC */	DEBUGP("final section addresses:\n");	for (i = 0; i < hdr->e_shnum; i++) {		void *dest;		if (!(sechdrs[i].sh_flags & SHF_ALLOC))			continue;		if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)			dest = mod->module_init				+ (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);		else			dest = mod->module_core + sechdrs[i].sh_entsize;		if (sechdrs[i].sh_type != SHT_NOBITS)			memcpy(dest, (void *)sechdrs[i].sh_addr,			       sechdrs[i].sh_size);		/* Update sh_addr to point to copy in image. */		sechdrs[i].sh_addr = (unsigned long)dest;		DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);	}	/* Module has been moved. */	mod = (void *)sechdrs[modindex].sh_addr;	/* Now we've moved module, initialize linked lists, etc. */	module_unload_init(mod);	/* Initialize kobject, so we can reference it. */	if (mod_sysfs_init(mod) != 0)		goto cleanup;	/* Set up license info based on the info section */	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));	if (strcmp(mod->name, "ndiswrapper") == 0)		add_taint(TAINT_PROPRIETARY_MODULE);	if (strcmp(mod->name, "driverloader") == 0)		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);	/* Set up MODINFO_ATTR fields */	setup_modinfo(mod, sechdrs, infoindex);	/* Fix up syms, so that st_value is a pointer to location. */	err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,			       mod);	if (err < 0)		goto cleanup;	/* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */	mod->num_syms = sechdrs[exportindex].sh_size / sizeof(*mod->syms);	mod->syms = (void *)sechdrs[exportindex].sh_addr;	if (crcindex)		mod->crcs = (void *)sechdrs[crcindex].sh_addr;	mod->num_gpl_syms = sechdrs[gplindex].sh_size / sizeof(*mod->gpl_syms);	mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr;	if (gplcrcindex)		mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;	mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /					sizeof(*mod->gpl_future_syms);	mod->num_unused_syms = sechdrs[unusedindex].sh_size /					sizeof(*mod->unused_syms);	mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /					sizeof(*mod->unused_gpl_syms);	mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;	if (gplfuturecrcindex)		mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;	mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;	if (unusedcrcindex)		mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;	mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;	if (unusedgplcrcindex)		mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;#ifdef CONFIG_MODVERSIONS	if ((mod->num_syms && !crcindex) || 	    (mod->num_gpl_syms && !gplcrcindex) ||	    (mod->num_gpl_future_syms && !gplfuturecrcindex) ||	    (mod->num_unused_syms && !unusedcrcindex) ||	    (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {		printk(KERN_WARNING "%s: No versions for exported symbols."		       " Tainting kernel.\n", mod->name);		add_taint_module(mod, TAINT_FORCED_MODULE);	}#endif	/* Now do relocations. */	for (i = 1; i < hdr->e_shnum; i++) {		const char *strtab = (char *)sechdrs[strindex].sh_addr;		unsigned int info = sechdrs[i].sh_info;		/* Not a valid relocation section? */		if (info >= hdr->e_shnum)			continue;		/* Don't bother with non-allocated sections */		if (!(sechdrs[info].sh_flags & SHF_ALLOC))			continue;		if (sechdrs[i].sh_type == SHT_REL)			err = apply_relocate(sechdrs, strtab, symindex, i,mod);		else if (sechdrs[i].sh_type == SHT_RELA)			err = apply_relocate_add(sechdrs, strtab, symindex, i,						 mod);		if (err < 0)			goto cleanup;	}        /* Find duplicate symbols */	err = verify_export_symbols(mod);	if (err < 0)		goto cleanup;  	/* Set up and sort exception table */	mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);	mod->extable = extable = (void *)sechdrs[exindex].sh_addr;	sort_extable(extable, extable + mod->num_exentries);	/* Finally, copy percpu area over. */	percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,		       sechdrs[pcpuindex].sh_size);	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);	err = module_finalize(hdr, sechdrs, mod);	if (err < 0)		goto cleanup;	/* 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);	mod->args = args;	if (obsparmindex)		printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",		       mod->name);	/* Size of section 0 is 0, so this works well if no params */	err = parse_args(mod->name, mod->args,			 (struct kernel_param *)			 sechdrs[setupindex].sh_addr,			 sechdrs[setupindex].sh_size			 / sizeof(struct kernel_param),			 NULL);	if (err < 0)		goto arch_cleanup;	err = mod_sysfs_setup(mod, 			      (struct kernel_param *)			      sechdrs[setupindex].sh_addr,			      sechdrs[setupindex].sh_size			      / sizeof(struct kernel_param));	if (err < 0)		goto arch_cleanup;	add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);	/* Size of section 0 is 0, so this works well if no unwind info. */	mod->unwind_info = unwind_add_table(mod,	                                    (void *)sechdrs[unwindex].sh_addr,	                                    sechdrs[unwindex].sh_size);	/* Get rid of temporary copy */	vfree(hdr);	/* Done! */	return mod; arch_cleanup:	module_arch_cleanup(mod); cleanup:	module_unload_free(mod);	module_free(mod, mod->module_init); free_core:	module_free(mod, mod->module_core); free_percpu:	if (percpu)		percpu_modfree(percpu); free_mod:	kfree(args); free_hdr:	vfree(hdr);	return ERR_PTR(err); truncated:	printk(KERN_ERR "Module len %lu truncated\n", len);	err = -ENOEXEC;	goto free_hdr;}/* * link the module with the whole machine is stopped with interrupts off * - this defends against kallsyms not taking locks */static int __link_module(void *_mod){	struct module *mod = _mod;	list_add(&mod->list, &modules);	return 0;}/* This is where the real work happens */asmlinkage longsys_init_module(void __user *umod,		unsigned long len,		const char __user *uargs){	struct module *mod;	int ret = 0;	/* Must have permission */	if (!capable(CAP_SYS_MODULE))		return -EPERM;	/* Only one module load at a time, please */	if (mutex_lock_interruptible(&module_mutex) != 0)		return -EINTR;	/* Do all the hard work */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -