diff options
-rw-r--r-- | kexec/kexec-elf-exec.c | 9 | ||||
-rw-r--r-- | kexec/kexec-elf-rel.c | 9 | ||||
-rw-r--r-- | kexec/kexec-elf.c | 24 | ||||
-rw-r--r-- | kexec/kexec-elf.h | 15 |
4 files changed, 35 insertions, 22 deletions
diff --git a/kexec/kexec-elf-exec.c b/kexec/kexec-elf-exec.c index ec00a05..f65a625 100644 --- a/kexec/kexec-elf-exec.c +++ b/kexec/kexec-elf-exec.c @@ -11,11 +11,12 @@ static const int probe_debug = 0; -int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr) +int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags) { struct mem_phdr *phdr, *end_phdr; int result; - result = build_elf_info(buf, len, ehdr); + result = build_elf_info(buf, len, ehdr, flags); if (result < 0) { return result; } @@ -136,11 +137,11 @@ int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info) } void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, - const char *buf, off_t len) + const char *buf, off_t len, uint32_t flags) { int result; /* Parse the Elf file */ - result = build_elf_exec_info(buf, len, ehdr); + result = build_elf_exec_info(buf, len, ehdr, flags); if (result < 0) { die("ELF exec parse failed\n"); } diff --git a/kexec/kexec-elf-rel.c b/kexec/kexec-elf-rel.c index ae78a09..4419937 100644 --- a/kexec/kexec-elf-rel.c +++ b/kexec/kexec-elf-rel.c @@ -135,10 +135,11 @@ static struct mem_rela elf_rela(struct mem_ehdr *ehdr, const unsigned char *ptr) return rela; } -int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr) +int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags) { int result; - result = build_elf_info(buf, len, ehdr); + result = build_elf_info(buf, len, ehdr, flags); if (result < 0) { return result; } @@ -419,12 +420,12 @@ int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info, void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, const char *buf, off_t len, unsigned long min, unsigned long max, - int end) + int end, uint32_t flags) { int result; /* Parse the Elf file */ - result = build_elf_rel_info(buf, len, ehdr); + result = build_elf_rel_info(buf, len, ehdr, flags); if (result < 0) { die("ELF rel parse failed\n"); } diff --git a/kexec/kexec-elf.c b/kexec/kexec-elf.c index da2c788..929c79c 100644 --- a/kexec/kexec-elf.c +++ b/kexec/kexec-elf.c @@ -368,7 +368,8 @@ static int build_mem_elf64_phdr(const char *buf, off_t len, return 0; } -static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr) +static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags) { size_t phdr_size, mem_phdr_size; int i; @@ -418,9 +419,11 @@ static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr) /* Check the program headers to be certain * they are safe to use. + * Skip the check if ELF_SKIP_FILESZ_CHECK is set. */ phdr = &ehdr->e_phdr[i]; - if ((phdr->p_offset + phdr->p_filesz) > len) { + if (!(flags & ELF_SKIP_FILESZ_CHECK) + && (phdr->p_offset + phdr->p_filesz) > len) { /* The segment does not fit in the buffer */ if (probe_debug) { fprintf(stderr, "ELF segment not in file\n"); @@ -580,7 +583,8 @@ static int build_mem_elf64_shdr(const char *buf, off_t len, return 0; } -static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr) +static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags) { size_t shdr_size, mem_shdr_size; int i; @@ -628,11 +632,12 @@ static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr) } /* Check the section headers to be certain * they are safe to use. + * Skip the check if ELF_SKIP_FILESZ_CHECK is set. */ shdr = &ehdr->e_shdr[i]; - if ((shdr->sh_type != SHT_NOBITS) && - ((shdr->sh_offset + shdr->sh_size) > len)) - { + if (!(flags & ELF_SKIP_FILESZ_CHECK) + && (shdr->sh_type != SHT_NOBITS) + && (shdr->sh_offset + shdr->sh_size) > len) { /* The section does not fit in the buffer */ if (probe_debug) { fprintf(stderr, "ELF section %d not in file\n", @@ -729,7 +734,8 @@ void free_elf_info(struct mem_ehdr *ehdr) memset(ehdr, 0, sizeof(*ehdr)); } -int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr) +int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags) { int result; result = build_mem_ehdr(buf, len, ehdr); @@ -737,14 +743,14 @@ int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr) return result; } if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) { - result = build_mem_phdrs(buf, len, ehdr); + result = build_mem_phdrs(buf, len, ehdr, flags); if (result < 0) { free_elf_info(ehdr); return result; } } if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) { - result = build_mem_shdrs(buf, len, ehdr); + result = build_mem_shdrs(buf, len, ehdr, flags); if (result < 0) { free_elf_info(ehdr); return result; diff --git a/kexec/kexec-elf.h b/kexec/kexec-elf.h index b7332de..0f09285 100644 --- a/kexec/kexec-elf.h +++ b/kexec/kexec-elf.h @@ -82,22 +82,27 @@ typedef struct uint32_t n_type; /* Type of the note. */ } ElfNN_Nhdr; +/* Misc flags */ +#define ELF_SKIP_FILESZ_CHECK 0x00000001 extern void free_elf_info(struct mem_ehdr *ehdr); -extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr); -extern int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr); -extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr); +extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags); +extern int build_elf_exec_info(const char *buf, off_t len, + struct mem_ehdr *ehdr, uint32_t flags); +extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags); extern int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info); extern int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info, unsigned long min, unsigned long max, int end); extern void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, - const char *buf, off_t len); + const char *buf, off_t len, uint32_t flags); extern void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, const char *buf, off_t len, unsigned long min, unsigned long max, - int end); + int end, uint32_t flags); extern int elf_rel_find_symbol(struct mem_ehdr *ehdr, const char *name, struct mem_sym *ret_sym); |