From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 41464 invoked by alias); 4 Oct 2017 18:57:42 -0000 Mailing-List: contact elfutils-devel-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: elfutils-devel-owner@sourceware.org Received: (qmail 40034 invoked by uid 89); 4 Oct 2017 18:57:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.2 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY autolearn=ham version=3.3.2 spammy=H*Ad:U*jistone, H*F:U*mark, U*mark X-Spam-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: gnu.wildebeest.org Received: from wildebeest.demon.nl (HELO gnu.wildebeest.org) (212.238.236.112) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 04 Oct 2017 18:57:40 +0000 Received: from tarox.wildebeest.org (tarox.wildebeest.org [172.31.17.39]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id 84E41302BB24; Wed, 4 Oct 2017 20:57:37 +0200 (CEST) Received: by tarox.wildebeest.org (Postfix, from userid 1000) id 7B05740216B6; Wed, 4 Oct 2017 20:57:37 +0200 (CEST) From: Mark Wielaard To: elfutils-devel@sourceware.org Cc: Josh Stone , Mark Wielaard Subject: [PATCH 1/2] libelf: Add ELF_E_INVALID_ELF error value. Date: Wed, 04 Oct 2017 18:57:00 -0000 Message-Id: <1507143449-19288-1-git-send-email-mark@klomp.org> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1507143353.9961.25.camel@klomp.org> References: <1507143353.9961.25.camel@klomp.org> X-IsSubscribed: yes X-SW-Source: 2017-q4/txt/msg00005.txt.bz2 Add ELF_E_INVALID_ELF which is set when the ELF file data is bad. This is different from ELF_E_INVALID_FILE which is set when the file could not be read. Signed-off-by: Mark Wielaard --- libelf/ChangeLog | 12 +++++++++ libelf/elf_begin.c | 61 ++++++++++++++++++++++++++++++++++------------ libelf/elf_error.c | 7 +++++- libelf/elf_getshdrstrndx.c | 20 ++++++++++----- libelf/libelfP.h | 1 + tests/ChangeLog | 4 +++ tests/msg_tst.c | 1 + 7 files changed, 83 insertions(+), 23 deletions(-) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 7bd9e1b..36b57dd 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,15 @@ +2017-10-04 Mark Wielaard + + * libelfP.h: Add ELF_E_INVALID_ELF to error values enum. + * elf_error.c (ELF_E_INVALID_ELF_IDX): New define. Use it as value + for ELF_E_INVALID_ELF in msgidx. + * elf_getshdrstrndx.c (elf_getshdrstrndx): Distinquish between pread + failing and not having enough data. + * elf_begin.c (get_shnum): Likewise. Explicitly set libelf errno on + too large value. + (file_read_elf): Make sure to always set libelf errno when returning + NULL. Distinquish between i/o file and elf data errors. + 2017-08-18 Ulf Hermann * gelf_xlate.c: Use attribute_packed. diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 6f85038..5545278 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -158,6 +158,7 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, else { Elf32_Word size; + ssize_t r; if (likely (map_address != NULL)) /* gcc will optimize the memcpy to a simple memory @@ -167,11 +168,19 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, + offset))->sh_size, sizeof (Elf32_Word)); else - if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word), - offset + ehdr.e32->e_shoff - + offsetof (Elf32_Shdr, sh_size)) + if (unlikely ((r = pread_retry (fildes, &size, + sizeof (Elf32_Word), + offset + ehdr.e32->e_shoff + + offsetof (Elf32_Shdr, + sh_size))) != sizeof (Elf32_Word))) - return (size_t) -1l; + { + if (r < 0) + __libelf_seterrno (ELF_E_INVALID_FILE); + else + __libelf_seterrno (ELF_E_INVALID_ELF); + return (size_t) -1l; + } if (e_ident[EI_DATA] != MY_ELFDATA) CONVERT (size); @@ -207,6 +216,7 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, + offset))->sh_size; else { + ssize_t r; if (likely (map_address != NULL)) /* gcc will optimize the memcpy to a simple memory access while taking care of alignment issues. */ @@ -215,19 +225,30 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset, + offset))->sh_size, sizeof (Elf64_Xword)); else - if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Xword), - offset + ehdr.e64->e_shoff - + offsetof (Elf64_Shdr, sh_size)) + if (unlikely ((r = pread_retry (fildes, &size, + sizeof (Elf64_Xword), + offset + ehdr.e64->e_shoff + + offsetof (Elf64_Shdr, + sh_size))) != sizeof (Elf64_Xword))) - return (size_t) -1l; + { + if (r < 0) + __libelf_seterrno (ELF_E_INVALID_FILE); + else + __libelf_seterrno (ELF_E_INVALID_ELF); + return (size_t) -1l; + } if (e_ident[EI_DATA] != MY_ELFDATA) CONVERT (size); } if (size > ~((GElf_Word) 0)) - /* Invalid value, it is too large. */ - return (size_t) -1l; + { + /* Invalid value, it is too large. */ + __libelf_seterrno (ELF_E_INVALID_ELF); + return (size_t) -1l; + } result = size; } @@ -255,11 +276,13 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, && e_ident[EI_DATA] != ELFDATA2MSB))) { /* Cannot handle this. */ - __libelf_seterrno (ELF_E_INVALID_FILE); + __libelf_seterrno (ELF_E_INVALID_ELF); return NULL; } - /* Determine the number of sections. */ + /* Determine the number of sections. Returns -1 and sets libelf errno + if the file handle or elf file is invalid. Returns zero if there + are no section headers (or they cannot be read). */ size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize); if (scncnt == (size_t) -1l) /* Could not determine the number of sections. */ @@ -269,10 +292,16 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, if (e_ident[EI_CLASS] == ELFCLASS32) { if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr))) - return NULL; + { + __libelf_seterrno (ELF_E_INVALID_ELF); + return NULL; + } } else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr))) - return NULL; + { + __libelf_seterrno (ELF_E_INVALID_ELF); + return NULL; + } /* We can now allocate the memory. Even if there are no section headers, we allocate space for a zeroth section in case we need it later. */ @@ -281,7 +310,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent, ELF_K_ELF, scnmax * sizeof (Elf_Scn)); if (elf == NULL) - /* Not enough memory. */ + /* Not enough memory. allocate_elf will have set libelf errno. */ return NULL; assert ((unsigned int) scncnt == scncnt); @@ -350,7 +379,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, { free_and_out: free (elf); - __libelf_seterrno (ELF_E_INVALID_FILE); + __libelf_seterrno (ELF_E_INVALID_ELF); return NULL; } elf->state.elf32.shdr diff --git a/libelf/elf_error.c b/libelf/elf_error.c index 888b389..5364e68 100644 --- a/libelf/elf_error.c +++ b/libelf/elf_error.c @@ -94,8 +94,12 @@ static const char msgstr[] = (ELF_E_NOMEM_IDX + sizeof "out of memory") N_("invalid file descriptor") "\0" -#define ELF_E_INVALID_OP_IDX \ +#define ELF_E_INVALID_ELF_IDX \ (ELF_E_INVALID_FILE_IDX + sizeof "invalid file descriptor") + N_("invalid ELF file data") + "\0" +#define ELF_E_INVALID_OP_IDX \ + (ELF_E_INVALID_ELF_IDX + sizeof "invalid ELF file data") N_("invalid operation") "\0" #define ELF_E_NO_VERSION_IDX \ @@ -280,6 +284,7 @@ static const uint_fast16_t msgidx[ELF_E_NUM] = [ELF_E_INVALID_ENCODING] = ELF_E_INVALID_ENCODING_IDX, [ELF_E_NOMEM] = ELF_E_NOMEM_IDX, [ELF_E_INVALID_FILE] = ELF_E_INVALID_FILE_IDX, + [ELF_E_INVALID_ELF] = ELF_E_INVALID_ELF_IDX, [ELF_E_INVALID_OP] = ELF_E_INVALID_OP_IDX, [ELF_E_NO_VERSION] = ELF_E_NO_VERSION_IDX, [ELF_E_INVALID_CMD] = ELF_E_INVALID_CMD_IDX, diff --git a/libelf/elf_getshdrstrndx.c b/libelf/elf_getshdrstrndx.c index aead2fe..ad884fd 100644 --- a/libelf/elf_getshdrstrndx.c +++ b/libelf/elf_getshdrstrndx.c @@ -133,13 +133,17 @@ elf_getshdrstrndx (Elf *elf, size_t *dst) /* We avoid reading in all the section headers. Just read the first one. */ Elf32_Shdr shdr_mem; + ssize_t r; - if (unlikely (pread_retry (elf->fildes, &shdr_mem, - sizeof (Elf32_Shdr), offset) + if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem, + sizeof (Elf32_Shdr), offset)) != sizeof (Elf32_Shdr))) { /* We must be able to read this ELF section header. */ - __libelf_seterrno (ELF_E_INVALID_FILE); + if (r < 0) + __libelf_seterrno (ELF_E_INVALID_FILE); + else + __libelf_seterrno (ELF_E_INVALID_ELF); result = -1; goto out; } @@ -194,13 +198,17 @@ elf_getshdrstrndx (Elf *elf, size_t *dst) /* We avoid reading in all the section headers. Just read the first one. */ Elf64_Shdr shdr_mem; + ssize_t r; - if (unlikely (pread_retry (elf->fildes, &shdr_mem, - sizeof (Elf64_Shdr), offset) + if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem, + sizeof (Elf64_Shdr), offset)) != sizeof (Elf64_Shdr))) { /* We must be able to read this ELF section header. */ - __libelf_seterrno (ELF_E_INVALID_FILE); + if (r < 0) + __libelf_seterrno (ELF_E_INVALID_FILE); + else + __libelf_seterrno (ELF_E_INVALID_ELF); result = -1; goto out; } diff --git a/libelf/libelfP.h b/libelf/libelfP.h index a4a0a3a..ca805ac 100644 --- a/libelf/libelfP.h +++ b/libelf/libelfP.h @@ -102,6 +102,7 @@ enum ELF_E_INVALID_ENCODING, ELF_E_NOMEM, ELF_E_INVALID_FILE, + ELF_E_INVALID_ELF, ELF_E_INVALID_OP, ELF_E_NO_VERSION, ELF_E_INVALID_CMD, diff --git a/tests/ChangeLog b/tests/ChangeLog index 7b6bf30..35688dc 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2017-10-04 Mark Wielaard + + * msg_tst.c: Handle ELF_E_INVALID_ELF. + 2017-09-10 Mark Wielaard * run-ar.sh: New test. diff --git a/tests/msg_tst.c b/tests/msg_tst.c index 7baea0a..aa974d0 100644 --- a/tests/msg_tst.c +++ b/tests/msg_tst.c @@ -39,6 +39,7 @@ static struct { ELF_E_INVALID_ENCODING, "invalid encoding" }, { ELF_E_NOMEM, "out of memory" }, { ELF_E_INVALID_FILE, "invalid file descriptor" }, + { ELF_E_INVALID_ELF, "invalid ELF file data" }, { ELF_E_INVALID_OP, "invalid operation" }, { ELF_E_NO_VERSION, "ELF version not set" }, { ELF_E_INVALID_CMD, "invalid command" }, -- 1.8.3.1