mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	module: setup load info before module_sig_check()
We want to be able to log the module name in early error messages, such as when module signature verification fails. Previously, the module name is set in layout_and_allocate(), meaning that any error messages that happen before (such as those in module_sig_check()) won't be logged with a module name, which isn't terribly helpful. In order to do this, reshuffle the order in load_module() and set up load info earlier so that we can log the module name along with these error messages. This requires splitting rewrite_section_headers() out of setup_load_info(). While we're at it, clean up and split up the operations done in layout_and_allocate(), setup_load_info(), and rewrite_section_headers() more cleanly so these functions only perform what their names suggest. Signed-off-by: Jessica Yu <jeyu@kernel.org>
This commit is contained in:
		
							parent
							
								
									81a0abd9f2
								
							
						
					
					
						commit
						5fdc7db644
					
				
					 1 changed files with 43 additions and 34 deletions
				
			
		| 
						 | 
					@ -2488,7 +2488,11 @@ static char *get_modinfo(struct load_info *info, const char *tag)
 | 
				
			||||||
	Elf_Shdr *infosec = &info->sechdrs[info->index.info];
 | 
						Elf_Shdr *infosec = &info->sechdrs[info->index.info];
 | 
				
			||||||
	unsigned long size = infosec->sh_size;
 | 
						unsigned long size = infosec->sh_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (p = (char *)infosec->sh_addr; p; p = next_string(p, &size)) {
 | 
						/*
 | 
				
			||||||
 | 
						 * get_modinfo() calls made before rewrite_section_headers()
 | 
				
			||||||
 | 
						 * must use sh_offset, as sh_addr isn't set!
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						for (p = (char *)info->hdr + infosec->sh_offset; p; p = next_string(p, &size)) {
 | 
				
			||||||
		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
 | 
							if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
 | 
				
			||||||
			return p + taglen + 1;
 | 
								return p + taglen + 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2928,17 +2932,7 @@ static int rewrite_section_headers(struct load_info *info, int flags)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Track but don't keep modinfo and version sections. */
 | 
						/* Track but don't keep modinfo and version sections. */
 | 
				
			||||||
	if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
 | 
					 | 
				
			||||||
		info->index.vers = 0; /* Pretend no __versions section! */
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		info->index.vers = find_sec(info, "__versions");
 | 
					 | 
				
			||||||
	info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
 | 
						info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	info->index.info = find_sec(info, ".modinfo");
 | 
					 | 
				
			||||||
	if (!info->index.info)
 | 
					 | 
				
			||||||
		info->name = "(missing .modinfo section)";
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		info->name = get_modinfo(info, "name");
 | 
					 | 
				
			||||||
	info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
 | 
						info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -2955,16 +2949,18 @@ static int rewrite_section_headers(struct load_info *info, int flags)
 | 
				
			||||||
static int setup_load_info(struct load_info *info, int flags)
 | 
					static int setup_load_info(struct load_info *info, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set up the convenience variables */
 | 
						/* Set up the convenience variables */
 | 
				
			||||||
	info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
 | 
						info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
 | 
				
			||||||
	info->secstrings = (void *)info->hdr
 | 
						info->secstrings = (void *)info->hdr
 | 
				
			||||||
		+ info->sechdrs[info->hdr->e_shstrndx].sh_offset;
 | 
							+ info->sechdrs[info->hdr->e_shstrndx].sh_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = rewrite_section_headers(info, flags);
 | 
						/* Try to find a name early so we can log errors with a module name */
 | 
				
			||||||
	if (err)
 | 
						info->index.info = find_sec(info, ".modinfo");
 | 
				
			||||||
		return err;
 | 
						if (!info->index.info)
 | 
				
			||||||
 | 
							info->name = "(missing .modinfo section)";
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							info->name = get_modinfo(info, "name");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Find internal symbols and strings. */
 | 
						/* Find internal symbols and strings. */
 | 
				
			||||||
	for (i = 1; i < info->hdr->e_shnum; i++) {
 | 
						for (i = 1; i < info->hdr->e_shnum; i++) {
 | 
				
			||||||
| 
						 | 
					@ -2977,6 +2973,11 @@ static int setup_load_info(struct load_info *info, int flags)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->index.sym == 0) {
 | 
				
			||||||
 | 
							pr_warn("%s: module has no symbols (stripped?)\n", info->name);
 | 
				
			||||||
 | 
							return -ENOEXEC;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
 | 
						info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
 | 
				
			||||||
	if (!info->index.mod) {
 | 
						if (!info->index.mod) {
 | 
				
			||||||
		pr_warn("%s: No module found in object\n",
 | 
							pr_warn("%s: No module found in object\n",
 | 
				
			||||||
| 
						 | 
					@ -2984,26 +2985,22 @@ static int setup_load_info(struct load_info *info, int flags)
 | 
				
			||||||
		return -ENOEXEC;
 | 
							return -ENOEXEC;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* This is temporary: point mod into copy of data. */
 | 
						/* This is temporary: point mod into copy of data. */
 | 
				
			||||||
	info->mod = (void *)info->sechdrs[info->index.mod].sh_addr;
 | 
						info->mod = (void *)info->hdr + info->sechdrs[info->index.mod].sh_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If we didn't load the .modinfo 'name' field, fall back to
 | 
						 * If we didn't load the .modinfo 'name' field earlier, fall back to
 | 
				
			||||||
	 * on-disk struct mod 'name' field.
 | 
						 * on-disk struct mod 'name' field.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (!info->name)
 | 
						if (!info->name)
 | 
				
			||||||
		info->name = info->mod->name;
 | 
							info->name = info->mod->name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (info->index.sym == 0) {
 | 
						if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
 | 
				
			||||||
		pr_warn("%s: module has no symbols (stripped?)\n", info->name);
 | 
							info->index.vers = 0; /* Pretend no __versions section! */
 | 
				
			||||||
		return -ENOEXEC;
 | 
						else
 | 
				
			||||||
	}
 | 
							info->index.vers = find_sec(info, "__versions");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info->index.pcpu = find_pcpusec(info);
 | 
						info->index.pcpu = find_pcpusec(info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check module struct version now, before we try to use module. */
 | 
					 | 
				
			||||||
	if (!check_modstruct_version(info, info->mod))
 | 
					 | 
				
			||||||
		return -ENOEXEC;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3303,13 +3300,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
 | 
				
			||||||
	unsigned int ndx;
 | 
						unsigned int ndx;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = setup_load_info(info, flags);
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		return ERR_PTR(err);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (blacklisted(info->name))
 | 
					 | 
				
			||||||
		return ERR_PTR(-EPERM);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = check_modinfo(info->mod, info, flags);
 | 
						err = check_modinfo(info->mod, info, flags);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return ERR_PTR(err);
 | 
							return ERR_PTR(err);
 | 
				
			||||||
| 
						 | 
					@ -3657,17 +3647,36 @@ static int load_module(struct load_info *info, const char __user *uargs,
 | 
				
			||||||
		       int flags)
 | 
							       int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct module *mod;
 | 
						struct module *mod;
 | 
				
			||||||
	long err;
 | 
						long err = 0;
 | 
				
			||||||
	char *after_dashes;
 | 
						char *after_dashes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = elf_header_check(info);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							goto free_copy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = setup_load_info(info, flags);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							goto free_copy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (blacklisted(info->name)) {
 | 
				
			||||||
 | 
							err = -EPERM;
 | 
				
			||||||
 | 
							goto free_copy;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = module_sig_check(info, flags);
 | 
						err = module_sig_check(info, flags);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		goto free_copy;
 | 
							goto free_copy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = elf_header_check(info);
 | 
						err = rewrite_section_headers(info, flags);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		goto free_copy;
 | 
							goto free_copy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check module struct version now, before we try to use module. */
 | 
				
			||||||
 | 
						if (!check_modstruct_version(info, info->mod)) {
 | 
				
			||||||
 | 
							err = -ENOEXEC;
 | 
				
			||||||
 | 
							goto free_copy;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Figure out module layout, and allocate all the memory. */
 | 
						/* Figure out module layout, and allocate all the memory. */
 | 
				
			||||||
	mod = layout_and_allocate(info, flags);
 | 
						mod = layout_and_allocate(info, flags);
 | 
				
			||||||
	if (IS_ERR(mod)) {
 | 
						if (IS_ERR(mod)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue