Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f71d977 authored by Sven Schnelle's avatar Sven Schnelle Committed by Helge Deller
Browse files

kexec_elf: remove parsing of section headers



We're not using them, so we can drop the parsing.

Signed-off-by: default avatarSven Schnelle <svens@stackframe.org>
Reviewed-by: default avatarThiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent d34e0ad3
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -226,7 +226,6 @@ struct kexec_elf_info {

	const struct elfhdr *ehdr;
	const struct elf_phdr *proghdrs;
	struct elf_shdr *sechdrs;
};

int kexec_build_elf_info(const char *buf, size_t len, struct elfhdr *ehdr,
+0 −137
Original line number Diff line number Diff line
@@ -257,134 +257,6 @@ static int elf_read_phdrs(const char *buf, size_t len,
	return 0;
}

/**
 * elf_is_shdr_sane - check that it is safe to use the section header
 * @buf_len:	size of the buffer in which the ELF file is loaded.
 */
static bool elf_is_shdr_sane(const struct elf_shdr *shdr, size_t buf_len)
{
	bool size_ok;

	/* SHT_NULL headers have undefined values, so we can't check them. */
	if (shdr->sh_type == SHT_NULL)
		return true;

	/* Now verify sh_entsize */
	switch (shdr->sh_type) {
	case SHT_SYMTAB:
		size_ok = shdr->sh_entsize == sizeof(Elf_Sym);
		break;
	case SHT_RELA:
		size_ok = shdr->sh_entsize == sizeof(Elf_Rela);
		break;
	case SHT_DYNAMIC:
		size_ok = shdr->sh_entsize == sizeof(Elf_Dyn);
		break;
	case SHT_REL:
		size_ok = shdr->sh_entsize == sizeof(Elf_Rel);
		break;
	case SHT_NOTE:
	case SHT_PROGBITS:
	case SHT_HASH:
	case SHT_NOBITS:
	default:
		/*
		 * This is a section whose entsize requirements
		 * I don't care about.  If I don't know about
		 * the section I can't care about it's entsize
		 * requirements.
		 */
		size_ok = true;
		break;
	}

	if (!size_ok) {
		pr_debug("ELF section with wrong entry size.\n");
		return false;
	} else if (shdr->sh_addr + shdr->sh_size < shdr->sh_addr) {
		pr_debug("ELF section address wraps around.\n");
		return false;
	}

	if (shdr->sh_type != SHT_NOBITS) {
		if (shdr->sh_offset + shdr->sh_size < shdr->sh_offset) {
			pr_debug("ELF section location wraps around.\n");
			return false;
		} else if (shdr->sh_offset + shdr->sh_size > buf_len) {
			pr_debug("ELF section not in file.\n");
			return false;
		}
	}

	return true;
}

static int elf_read_shdr(const char *buf, size_t len,
			 struct kexec_elf_info *elf_info,
			 int idx)
{
	struct elf_shdr *shdr = &elf_info->sechdrs[idx];
	const struct elfhdr *ehdr = elf_info->ehdr;
	const char *sbuf;
	struct elf_shdr *buf_shdr;

	sbuf = buf + ehdr->e_shoff + idx * sizeof(*buf_shdr);
	buf_shdr = (struct elf_shdr *) sbuf;

	shdr->sh_name      = elf32_to_cpu(ehdr, buf_shdr->sh_name);
	shdr->sh_type      = elf32_to_cpu(ehdr, buf_shdr->sh_type);
	shdr->sh_addr      = elf_addr_to_cpu(ehdr, buf_shdr->sh_addr);
	shdr->sh_offset    = elf_addr_to_cpu(ehdr, buf_shdr->sh_offset);
	shdr->sh_link      = elf32_to_cpu(ehdr, buf_shdr->sh_link);
	shdr->sh_info      = elf32_to_cpu(ehdr, buf_shdr->sh_info);

	/*
	 * The following fields have a type equivalent to Elf_Addr
	 * both in 32 bit and 64 bit ELF.
	 */
	shdr->sh_flags     = elf_addr_to_cpu(ehdr, buf_shdr->sh_flags);
	shdr->sh_size      = elf_addr_to_cpu(ehdr, buf_shdr->sh_size);
	shdr->sh_addralign = elf_addr_to_cpu(ehdr, buf_shdr->sh_addralign);
	shdr->sh_entsize   = elf_addr_to_cpu(ehdr, buf_shdr->sh_entsize);

	return elf_is_shdr_sane(shdr, len) ? 0 : -ENOEXEC;
}

/**
 * elf_read_shdrs - read the section headers from the buffer
 *
 * This function assumes that the section header table was checked for sanity.
 * Use elf_is_ehdr_sane() if it wasn't.
 */
static int elf_read_shdrs(const char *buf, size_t len,
			  struct kexec_elf_info *elf_info)
{
	size_t shdr_size, i;

	/*
	 * e_shnum is at most 65536 so calculating
	 * the size of the section header cannot overflow.
	 */
	shdr_size = sizeof(struct elf_shdr) * elf_info->ehdr->e_shnum;

	elf_info->sechdrs = kzalloc(shdr_size, GFP_KERNEL);
	if (!elf_info->sechdrs)
		return -ENOMEM;

	for (i = 0; i < elf_info->ehdr->e_shnum; i++) {
		int ret;

		ret = elf_read_shdr(buf, len, elf_info, i);
		if (ret) {
			kfree(elf_info->sechdrs);
			elf_info->sechdrs = NULL;
			return ret;
		}
	}

	return 0;
}

/**
 * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
 * @buf:	Buffer to read ELF file from.
@@ -417,14 +289,6 @@ static int elf_read_from_buffer(const char *buf, size_t len,
		if (ret)
			return ret;
	}
	if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
		ret = elf_read_shdrs(buf, len, elf_info);
		if (ret) {
			kfree(elf_info->proghdrs);
			return ret;
		}
	}

	return 0;
}

@@ -434,7 +298,6 @@ static int elf_read_from_buffer(const char *buf, size_t len,
void kexec_free_elf_info(struct kexec_elf_info *elf_info)
{
	kfree(elf_info->proghdrs);
	kfree(elf_info->sechdrs);
	memset(elf_info, 0, sizeof(*elf_info));
}
/**