summaryrefslogtreecommitdiff
path: root/lib/libelf
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2019-03-19 02:31:36 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2019-03-19 02:31:36 +0000
commitcf0274fe9f59233533a1cc96887748298971c367 (patch)
treeb9c80402e35d2d4f5ff38a750476ab4c3dd26915 /lib/libelf
parente69491f952dc7794ee3a52e768fa6028c5be8e0b (diff)
update libelf from elftoolchain r3669 to r3714
includes changes to address problems sunil@ found with fuzzing original diff from and ok sunil@
Diffstat (limited to 'lib/libelf')
-rw-r--r--lib/libelf/_libelf.h4
-rw-r--r--lib/libelf/elf.347
-rw-r--r--lib/libelf/elf_data.c15
-rw-r--r--lib/libelf/elf_end.c4
-rw-r--r--lib/libelf/elf_getident.c4
-rw-r--r--lib/libelf/elf_next.37
-rw-r--r--lib/libelf/elf_next.c16
-rw-r--r--lib/libelf/elf_rand.c14
-rw-r--r--lib/libelf/elf_rawfile.c6
-rw-r--r--lib/libelf/elf_scn.c7
-rw-r--r--lib/libelf/elf_update.c8
-rw-r--r--lib/libelf/libelf_allocate.c31
-rw-r--r--lib/libelf/libelf_ar.c43
-rw-r--r--lib/libelf/libelf_convert.m413
-rw-r--r--lib/libelf/libelf_ehdr.c11
-rw-r--r--lib/libelf/libelf_extended.c12
-rw-r--r--lib/libelf/libelf_memory.c4
-rw-r--r--lib/libelf/libelf_phdr.c7
18 files changed, 156 insertions, 97 deletions
diff --git a/lib/libelf/_libelf.h b/lib/libelf/_libelf.h
index a437aeda825..8531ba3cb59 100644
--- a/lib/libelf/_libelf.h
+++ b/lib/libelf/_libelf.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: _libelf.h,v 1.1 2019/02/01 05:27:37 jsg Exp $
+ * $Id: _libelf.h,v 1.2 2019/03/19 02:31:35 jsg Exp $
*/
#ifndef __LIBELF_H_
@@ -90,7 +90,7 @@ struct _Elf {
Elf_Kind e_kind; /* ELF_K_* */
Elf *e_parent; /* non-NULL for archive members */
unsigned char *e_rawfile; /* uninterpreted bytes */
- size_t e_rawsize; /* size of uninterpreted bytes */
+ off_t e_rawsize; /* size of uninterpreted bytes */
unsigned int e_version; /* file version */
/*
diff --git a/lib/libelf/elf.3 b/lib/libelf/elf.3
index 93a072bb4ec..f946fb936b8 100644
--- a/lib/libelf/elf.3
+++ b/lib/libelf/elf.3
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2006-2008,2011 Joseph Koshy. All rights reserved.
+.\" Copyright (c) 2006-2008,2011,2019 Joseph Koshy. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
-.\" $Id: elf.3,v 1.1 2019/02/01 05:27:37 jsg Exp $
+.\" $Id: elf.3,v 1.2 2019/03/19 02:31:35 jsg Exp $
.\"
-.Dd October 10, 2018
+.Dd February 5, 2019
.Dt ELF 3
.Os
.Sh NAME
@@ -266,36 +266,43 @@ The operating version for the data in this buffer.
.El
.Pp
.Vt Elf_Data
-descriptors are usually associated with
+descriptors are usually used in conjunction with
.Vt Elf_Scn
descriptors.
-Existing data descriptors associated with an ELF section may be
-structures are retrieved using the
-.Fn elf_getdata
-and
-.Fn elf_rawdata
-functions.
-The
-.Fn elf_newdata
-function may be used to attach new data descriptors to an ELF section.
.It Vt Elf_Scn
.Vt Elf_Scn
-descriptors represent a section in an ELF object.
+descriptors represent sections in an ELF object.
+These descriptors are opaque and contain no application modifiable
+fields.
.Pp
-They are retrieved using the
+The
+.Vt Elf_Scn
+descriptor for a specific section in an ELF object can be
+retrieved using the
.Fn elf_getscn
function.
-An application may iterate through the existing sections of an ELF
-object using the
+The sections contained in an ELF object can be traversed using the
.Fn elf_nextscn
function.
-New sections may be allocated using the
+New sections are allocated using the
.Fn elf_newscn
function.
.Pp
The
-.Vt Elf_Scn
-descriptor is opaque and contains no application modifiable fields.
+.Vt Elf_Data
+descriptors associated with a given section can be retrieved
+using the
+.Fn elf_getdata
+function.
+New data descriptors can be added to a section
+descriptor using the
+.Fn elf_newdata
+function.
+The untranslated
+.Dq file
+representation of data in a section can be retrieved using the
+.Fn elf_rawdata
+function.
.El
.Ss Supported Elf Types
The following ELF datatypes are supported by the library.
diff --git a/lib/libelf/elf_data.c b/lib/libelf/elf_data.c
index a8178b3ccc4..4164f67763d 100644
--- a/lib/libelf/elf_data.c
+++ b/lib/libelf/elf_data.c
@@ -32,7 +32,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: elf_data.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_data.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *ed)
@@ -42,7 +42,7 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
int elfclass, elftype;
size_t count, fsz, msz;
struct _Libelf_Data *d;
- uint64_t sh_align, sh_offset, sh_size;
+ uint64_t sh_align, sh_offset, sh_size, raw_size;
_libelf_translator_function *xlate;
d = (struct _Libelf_Data *) ed;
@@ -59,7 +59,8 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
return (&d->d_data);
if (d != NULL)
- return (&STAILQ_NEXT(d, d_next)->d_data);
+ return (STAILQ_NEXT(d, d_next) ?
+ &STAILQ_NEXT(d, d_next)->d_data : NULL);
if (e->e_rawfile == NULL) {
/*
@@ -91,9 +92,10 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed)
return (NULL);
}
+ raw_size = (uint64_t) e->e_rawsize;
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
- (sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset))) {
+ (sh_offset > raw_size || sh_size > raw_size - sh_offset))) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
@@ -215,7 +217,7 @@ elf_rawdata(Elf_Scn *s, Elf_Data *ed)
int elf_class;
uint32_t sh_type;
struct _Libelf_Data *d;
- uint64_t sh_align, sh_offset, sh_size;
+ uint64_t sh_align, sh_offset, sh_size, raw_size;
if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
LIBELF_SET_ERROR(ARGUMENT, 0);
@@ -253,8 +255,9 @@ elf_rawdata(Elf_Scn *s, Elf_Data *ed)
return (NULL);
}
+ raw_size = (uint64_t) e->e_rawsize;
if (sh_type != SHT_NOBITS &&
- (sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset)) {
+ (sh_offset > raw_size || sh_size > raw_size - sh_offset)) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
diff --git a/lib/libelf/elf_end.c b/lib/libelf/elf_end.c
index fc32ddd5d17..84820feb302 100644
--- a/lib/libelf/elf_end.c
+++ b/lib/libelf/elf_end.c
@@ -34,7 +34,7 @@
#include <sys/mman.h>
#endif
-ELFTC_VCSID("$Id: elf_end.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_end.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
int
elf_end(Elf *e)
@@ -81,7 +81,7 @@ elf_end(Elf *e)
free(e->e_rawfile);
#if ELFTC_HAVE_MMAP
else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
- (void) munmap(e->e_rawfile, e->e_rawsize);
+ (void) munmap(e->e_rawfile, (size_t) e->e_rawsize);
#endif
}
diff --git a/lib/libelf/elf_getident.c b/lib/libelf/elf_getident.c
index dfac40421d6..0c24d707768 100644
--- a/lib/libelf/elf_getident.c
+++ b/lib/libelf/elf_getident.c
@@ -30,7 +30,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: elf_getident.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_getident.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
char *
elf_getident(Elf *e, size_t *sz)
@@ -54,7 +54,7 @@ elf_getident(Elf *e, size_t *sz)
else if (e->e_kind == ELF_K_ELF)
*sz = EI_NIDENT;
else
- *sz = e->e_rawsize;
+ *sz = (size_t) e->e_rawsize;
}
return ((char *) e->e_rawfile);
diff --git a/lib/libelf/elf_next.3 b/lib/libelf/elf_next.3
index e7982f9ea6e..77b5722c022 100644
--- a/lib/libelf/elf_next.3
+++ b/lib/libelf/elf_next.3
@@ -21,9 +21,9 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
-.\" $Id: elf_next.3,v 1.1 2019/02/01 05:27:37 jsg Exp $
+.\" $Id: elf_next.3,v 1.2 2019/03/19 02:31:35 jsg Exp $
.\"
-.Dd June 17, 2006
+.Dd February 27, 2019
.Dt ELF_NEXT 3
.Os
.Sh NAME
@@ -88,6 +88,9 @@ Argument
was not associated with a containing
.Xr ar 1
archive.
+.It Bq Er ELF_E_ARGUMENT
+An error was encountered while parsing the archive containing argument
+.Ar elf .
.El
.Sh SEE ALSO
.Xr elf 3 ,
diff --git a/lib/libelf/elf_next.c b/lib/libelf/elf_next.c
index 74f9b9975cf..d08a37d35fb 100644
--- a/lib/libelf/elf_next.c
+++ b/lib/libelf/elf_next.c
@@ -30,7 +30,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: elf_next.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_next.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
Elf_Cmd
elf_next(Elf *e)
@@ -60,5 +60,19 @@ elf_next(Elf *e)
parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ?
(off_t) 0 : next;
+ /*
+ * Return an error if the 'e_next' field falls outside the current
+ * file.
+ *
+ * This check is performed after updating the parent descriptor's
+ * 'e_next' field so that the next call to elf_begin(3) will terminate
+ * traversal of a too-small archive even if client code forgets to
+ * check the return value from elf_next(3).
+ */
+ if (next > (off_t) parent->e_rawsize) {
+ LIBELF_SET_ERROR(ARGUMENT, 0);
+ return (ELF_C_NULL);
+ }
+
return (ELF_C_READ);
}
diff --git a/lib/libelf/elf_rand.c b/lib/libelf/elf_rand.c
index e5211034cb7..636808c84e3 100644
--- a/lib/libelf/elf_rand.c
+++ b/lib/libelf/elf_rand.c
@@ -26,19 +26,29 @@
#include <ar.h>
#include <libelf.h>
+#include <stdint.h>
#include "_libelf.h"
-ELFTC_VCSID("$Id: elf_rand.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_rand.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
off_t
elf_rand(Elf *ar, off_t offset)
{
struct ar_hdr *arh;
+ off_t offset_of_member;
+
+ offset_of_member = offset + (off_t) sizeof(struct ar_hdr);
if (ar == NULL || ar->e_kind != ELF_K_AR ||
(offset & 1) || offset < SARMAG ||
- (size_t) offset + sizeof(struct ar_hdr) >= ar->e_rawsize) {
+ offset_of_member >= ar->e_rawsize) {
+ LIBELF_SET_ERROR(ARGUMENT, 0);
+ return 0;
+ }
+
+ /* Check for numeric overflow. */
+ if ((uintmax_t) offset_of_member < (uintmax_t) offset) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return 0;
}
diff --git a/lib/libelf/elf_rawfile.c b/lib/libelf/elf_rawfile.c
index 9047c3d54db..081caf30f9f 100644
--- a/lib/libelf/elf_rawfile.c
+++ b/lib/libelf/elf_rawfile.c
@@ -28,15 +28,13 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: elf_rawfile.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_rawfile.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
char *
elf_rawfile(Elf *e, size_t *sz)
{
- size_t size;
unsigned char *ptr;
- size = e ? e->e_rawsize : 0;
ptr = NULL;
if (e == NULL)
@@ -45,7 +43,7 @@ elf_rawfile(Elf *e, size_t *sz)
LIBELF_SET_ERROR(SEQUENCE, 0);
if (sz)
- *sz = size;
+ *sz = e ? (size_t) e->e_rawsize : 0;
return ((char *) ptr);
}
diff --git a/lib/libelf/elf_scn.c b/lib/libelf/elf_scn.c
index 42cf3f53eab..ef9ac04a17c 100644
--- a/lib/libelf/elf_scn.c
+++ b/lib/libelf/elf_scn.c
@@ -36,7 +36,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: elf_scn.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_scn.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
/*
* Load an ELF section table and create a list of Elf_Scn structures.
@@ -58,10 +58,11 @@ _libelf_load_section_headers(Elf *e, void *ehdr)
assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);
#define CHECK_EHDR(E,EH) do { \
- if (shoff > e->e_rawsize || \
+ uintmax_t rawsize = (uintmax_t) e->e_rawsize; \
+ if (shoff > (uintmax_t) e->e_rawsize || \
fsz != (EH)->e_shentsize || \
shnum > SIZE_MAX / fsz || \
- fsz * shnum > e->e_rawsize - shoff) { \
+ fsz * shnum > rawsize - shoff) { \
LIBELF_SET_ERROR(HEADER, 0); \
return (0); \
} \
diff --git a/lib/libelf/elf_update.c b/lib/libelf/elf_update.c
index ae0f546386e..880fd1a0e62 100644
--- a/lib/libelf/elf_update.c
+++ b/lib/libelf/elf_update.c
@@ -41,7 +41,7 @@
#include <sys/mman.h>
#endif
-ELFTC_VCSID("$Id: elf_update.c,v 1.1 2019/02/01 05:27:37 jsg Exp $");
+ELFTC_VCSID("$Id: elf_update.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
/*
* Layout strategy:
@@ -142,7 +142,7 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS);
elftype = _libelf_xlate_shtype(sh_type);
- if (elftype > ELF_T_LAST) {
+ if (elftype < ELF_T_FIRST || elftype > ELF_T_LAST) {
LIBELF_SET_ERROR(SECTION, 0);
return (0);
}
@@ -1084,7 +1084,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
assert(e->e_rawfile != NULL);
assert(e->e_cmd == ELF_C_RDWR);
- if (munmap(e->e_rawfile, e->e_rawsize) < 0) {
+ if (munmap(e->e_rawfile, (size_t) e->e_rawsize) < 0) {
LIBELF_SET_ERROR(IO, errno);
goto error;
}
@@ -1125,7 +1125,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
#endif /* ELFTC_HAVE_MMAP */
/* Record the new size of the file. */
- e->e_rawsize = (size_t) newsize;
+ e->e_rawsize = newsize;
} else {
/* File opened in ELF_C_WRITE mode. */
assert(e->e_rawfile == NULL);
diff --git a/lib/libelf/libelf_allocate.c b/lib/libelf/libelf_allocate.c
index 84f85237562..441dbcbab55 100644
--- a/lib/libelf/libelf_allocate.c
+++ b/lib/libelf/libelf_allocate.c
@@ -36,33 +36,26 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: libelf_allocate.c,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_allocate.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
Elf *
_libelf_allocate_elf(void)
{
Elf *e;
- if ((e = malloc(sizeof(*e))) == NULL) {
+ if ((e = calloc((size_t) 1, sizeof(*e))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, errno);
return NULL;
}
e->e_activations = 1;
- e->e_hdr.e_rawhdr = NULL;
e->e_byteorder = ELFDATANONE;
e->e_class = ELFCLASSNONE;
e->e_cmd = ELF_C_NULL;
e->e_fd = -1;
- e->e_flags = 0;
e->e_kind = ELF_K_NONE;
- e->e_parent = NULL;
- e->e_rawfile = NULL;
- e->e_rawsize = 0;
e->e_version = LIBELF_PRIVATE(version);
- (void) memset(&e->e_u, 0, sizeof(e->e_u));
-
return (e);
}
@@ -83,12 +76,6 @@ _libelf_init_elf(Elf *e, Elf_Kind kind)
}
}
-#define FREE(P) do { \
- if (P) \
- free(P); \
- } while (0)
-
-
Elf *
_libelf_release_elf(Elf *e)
{
@@ -96,18 +83,18 @@ _libelf_release_elf(Elf *e)
switch (e->e_kind) {
case ELF_K_AR:
- FREE(e->e_u.e_ar.e_symtab);
+ free(e->e_u.e_ar.e_symtab);
break;
case ELF_K_ELF:
switch (e->e_class) {
case ELFCLASS32:
- FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
- FREE(e->e_u.e_elf.e_phdr.e_phdr32);
+ free(e->e_u.e_elf.e_ehdr.e_ehdr32);
+ free(e->e_u.e_elf.e_phdr.e_phdr32);
break;
case ELFCLASS64:
- FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
- FREE(e->e_u.e_elf.e_phdr.e_phdr64);
+ free(e->e_u.e_elf.e_ehdr.e_ehdr64);
+ free(e->e_u.e_elf.e_phdr.e_phdr64);
break;
}
@@ -115,8 +102,8 @@ _libelf_release_elf(Elf *e)
if (e->e_flags & LIBELF_F_AR_HEADER) {
arh = e->e_hdr.e_arhdr;
- FREE(arh->ar_name);
- FREE(arh->ar_rawname);
+ free(arh->ar_name);
+ free(arh->ar_rawname);
free(arh);
}
diff --git a/lib/libelf/libelf_ar.c b/lib/libelf/libelf_ar.c
index 368239bd409..273111ae4af 100644
--- a/lib/libelf/libelf_ar.c
+++ b/lib/libelf/libelf_ar.c
@@ -34,7 +34,7 @@
#include "_libelf.h"
#include "_libelf_ar.h"
-ELFTC_VCSID("$Id: libelf_ar.c,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_ar.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
#define LIBELF_NALLOC_SIZE 16
@@ -124,8 +124,16 @@ _libelf_ar_gethdr(Elf *e)
arh = (struct ar_hdr *) (uintptr_t) e->e_hdr.e_rawhdr;
assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG);
- assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile +
- parent->e_rawsize - sizeof(struct ar_hdr));
+
+ /*
+ * There needs to be enough space remaining in the file for the
+ * archive header.
+ */
+ if ((uintptr_t) arh > (uintptr_t) parent->e_rawfile +
+ (uintptr_t) parent->e_rawsize - sizeof(struct ar_hdr)) {
+ LIBELF_SET_ERROR(ARCHIVE, 0);
+ return (NULL);
+ }
if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
@@ -200,8 +208,8 @@ Elf *
_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
{
Elf *e;
- off_t next;
size_t nsz, sz;
+ off_t next, end;
struct ar_hdr *arh;
char *member, *namelen;
@@ -218,6 +226,17 @@ _libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
assert((next & 1) == 0);
+ /*
+ * There needs to be enough space in the file to contain an
+ * ar(1) header.
+ */
+ end = next + (off_t) sizeof(struct ar_hdr);
+ if ((uintmax_t) end < (uintmax_t) next || /* Overflow. */
+ end > (off_t) elf->e_rawsize) {
+ LIBELF_SET_ERROR(ARCHIVE, 0);
+ return (NULL);
+ }
+
arh = (struct ar_hdr *) (elf->e_rawfile + next);
/*
@@ -230,6 +249,17 @@ _libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
}
/*
+ * Check if the archive member that follows will fit in the
+ * containing archive.
+ */
+ end += (off_t) sz;
+ if (end < next || /* Overflow. */
+ end > (off_t) elf->e_rawsize) {
+ LIBELF_SET_ERROR(ARCHIVE, 0);
+ return (NULL);
+ }
+
+ /*
* Adjust the size field for members in BSD archives using
* extended naming.
*/
@@ -287,7 +317,8 @@ Elf_Arsym *
_libelf_ar_process_bsd_symtab(Elf *e, size_t *count)
{
Elf_Arsym *symtab, *sym;
- unsigned int n, nentries;
+ unsigned int n;
+ size_t nentries;
unsigned char *end, *p, *p0, *s, *s0;
const size_t entrysize = 2 * sizeof(long);
long arraysize, fileoffset, stroffset, strtabsize;
@@ -344,7 +375,7 @@ _libelf_ar_process_bsd_symtab(Elf *e, size_t *count)
GET_LONG(p, fileoffset);
if (stroffset < 0 || fileoffset < 0 ||
- (size_t) fileoffset >= e->e_rawsize)
+ (off_t) fileoffset >= e->e_rawsize)
goto symtaberror;
s = s0 + stroffset;
diff --git a/lib/libelf/libelf_convert.m4 b/lib/libelf/libelf_convert.m4
index a063076bb07..af3282a2378 100644
--- a/lib/libelf/libelf_convert.m4
+++ b/lib/libelf/libelf_convert.m4
@@ -31,7 +31,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: libelf_convert.m4,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_convert.m4,v 1.2 2019/03/19 02:31:35 jsg Exp $");
/* WARNING: GENERATED FROM __file__. */
@@ -821,7 +821,7 @@ _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src,
if (dsz < srcsz) /* Destination lacks space. */
return (0);
- nchains = srcsz / sizeof(uint32_t);
+ nchains = (uint32_t) (srcsz / sizeof(uint32_t));
chains = (uint32_t *) (uintptr_t) dst;
for (n = 0; n < nchains; n++) {
@@ -902,7 +902,7 @@ _libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src,
if (dsz < srcsz)
return (0);
- nchains = srcsz / sizeof(uint32_t);
+ nchains = (uint32_t) (srcsz / sizeof(uint32_t));
for (n = 0; n < nchains; n++) {
t32 = *s32++;
if (byteswap)
@@ -1079,13 +1079,8 @@ _libelf_translator_function *
_libelf_get_translator(Elf_Type t, int direction, int elfclass, int elfmachine)
{
assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
- assert(elfmachine >= EM_NONE && elfmachine < EM__LAST__);
assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);
-
- if (t >= ELF_T_NUM ||
- (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) ||
- (direction != ELF_TOFILE && direction != ELF_TOMEMORY))
- return (NULL);
+ assert(t >= ELF_T_FIRST && t <= ELF_T_LAST);
/* TODO: Handle MIPS64 REL{,A} sections (ticket #559). */
(void) elfmachine;
diff --git a/lib/libelf/libelf_ehdr.c b/lib/libelf/libelf_ehdr.c
index 8a3624f021e..ef82463c852 100644
--- a/lib/libelf/libelf_ehdr.c
+++ b/lib/libelf/libelf_ehdr.c
@@ -31,7 +31,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: libelf_ehdr.c,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_ehdr.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
/*
* Retrieve counts for sections, phdrs and the section string table index
@@ -51,7 +51,12 @@ _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
assert(fsz > 0);
- if (e->e_rawsize < shoff + fsz) { /* raw file too small */
+ if (shoff + fsz < shoff) { /* Numeric overflow. */
+ LIBELF_SET_ERROR(HEADER, 0);
+ return (0);
+ }
+
+ if ((uint64_t) e->e_rawsize < shoff + fsz) {
LIBELF_SET_ERROR(HEADER, 0);
return (0);
}
@@ -138,7 +143,7 @@ _libelf_ehdr(Elf *e, int ec, int allocate)
fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
assert(fsz > 0);
- if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
+ if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < (off_t) fsz) {
LIBELF_SET_ERROR(HEADER, 0);
return (NULL);
}
diff --git a/lib/libelf/libelf_extended.c b/lib/libelf/libelf_extended.c
index 6190ff56d6e..d42bdabd088 100644
--- a/lib/libelf/libelf_extended.c
+++ b/lib/libelf/libelf_extended.c
@@ -29,7 +29,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: libelf_extended.c,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_extended.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
/*
* Retrieve section #0, allocating a new section if needed.
@@ -57,7 +57,7 @@ _libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
assert(scn->s_ndx == SHN_UNDEF);
if (ec == ELFCLASS32)
- scn->s_shdr.s_shdr32.sh_size = shnum;
+ scn->s_shdr.s_shdr32.sh_size = (Elf32_Word) shnum;
else
scn->s_shdr.s_shdr64.sh_size = shnum;
@@ -87,9 +87,9 @@ _libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx)
assert(scn->s_ndx == SHN_UNDEF);
if (ec == ELFCLASS32)
- scn->s_shdr.s_shdr32.sh_link = shstrndx;
+ scn->s_shdr.s_shdr32.sh_link = (Elf32_Word) shstrndx;
else
- scn->s_shdr.s_shdr64.sh_link = shstrndx;
+ scn->s_shdr.s_shdr64.sh_link = (Elf64_Word) shstrndx;
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
@@ -116,9 +116,9 @@ _libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum)
assert(scn->s_ndx == SHN_UNDEF);
if (ec == ELFCLASS32)
- scn->s_shdr.s_shdr32.sh_info = phnum;
+ scn->s_shdr.s_shdr32.sh_info = (Elf32_Word) phnum;
else
- scn->s_shdr.s_shdr64.sh_info = phnum;
+ scn->s_shdr.s_shdr64.sh_info = (Elf64_Word) phnum;
(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
diff --git a/lib/libelf/libelf_memory.c b/lib/libelf/libelf_memory.c
index 550211b689f..705bebe17b6 100644
--- a/lib/libelf/libelf_memory.c
+++ b/lib/libelf/libelf_memory.c
@@ -31,7 +31,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: libelf_memory.c,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_memory.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
/*
* Create an ELF descriptor for a memory image, optionally reporting
@@ -54,7 +54,7 @@ _libelf_memory(unsigned char *image, size_t sz, int reporterror)
e->e_cmd = ELF_C_READ;
e->e_rawfile = image;
- e->e_rawsize = sz;
+ e->e_rawsize = (off_t) sz;
#undef LIBELF_IS_ELF
#define LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && \
diff --git a/lib/libelf/libelf_phdr.c b/lib/libelf/libelf_phdr.c
index 8196ba426de..797a66977f0 100644
--- a/lib/libelf/libelf_phdr.c
+++ b/lib/libelf/libelf_phdr.c
@@ -31,7 +31,7 @@
#include "_libelf.h"
-ELFTC_VCSID("$Id: libelf_phdr.c,v 1.1 2019/02/01 05:27:38 jsg Exp $");
+ELFTC_VCSID("$Id: libelf_phdr.c,v 1.2 2019/03/19 02:31:35 jsg Exp $");
void *
_libelf_getphdr(Elf *e, int ec)
@@ -77,6 +77,11 @@ _libelf_getphdr(Elf *e, int ec)
assert(fsz > 0);
+ if (phoff + fsz < phoff) { /* Numeric overflow. */
+ LIBELF_SET_ERROR(HEADER, 0);
+ return (NULL);
+ }
+
if ((uint64_t) e->e_rawsize < (phoff + fsz)) {
LIBELF_SET_ERROR(HEADER, 0);
return (NULL);