Loading include/linux/kexec.h +0 −1 Original line number Diff line number Diff line Loading @@ -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, Loading kernel/kexec_elf.c +0 −137 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; } Loading @@ -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)); } /** Loading Loading
include/linux/kexec.h +0 −1 Original line number Diff line number Diff line Loading @@ -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, Loading
kernel/kexec_elf.c +0 −137 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; } Loading @@ -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)); } /** Loading