diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2019-03-19 02:31:36 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2019-03-19 02:31:36 +0000 |
commit | cf0274fe9f59233533a1cc96887748298971c367 (patch) | |
tree | b9c80402e35d2d4f5ff38a750476ab4c3dd26915 /lib/libelf | |
parent | e69491f952dc7794ee3a52e768fa6028c5be8e0b (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.h | 4 | ||||
-rw-r--r-- | lib/libelf/elf.3 | 47 | ||||
-rw-r--r-- | lib/libelf/elf_data.c | 15 | ||||
-rw-r--r-- | lib/libelf/elf_end.c | 4 | ||||
-rw-r--r-- | lib/libelf/elf_getident.c | 4 | ||||
-rw-r--r-- | lib/libelf/elf_next.3 | 7 | ||||
-rw-r--r-- | lib/libelf/elf_next.c | 16 | ||||
-rw-r--r-- | lib/libelf/elf_rand.c | 14 | ||||
-rw-r--r-- | lib/libelf/elf_rawfile.c | 6 | ||||
-rw-r--r-- | lib/libelf/elf_scn.c | 7 | ||||
-rw-r--r-- | lib/libelf/elf_update.c | 8 | ||||
-rw-r--r-- | lib/libelf/libelf_allocate.c | 31 | ||||
-rw-r--r-- | lib/libelf/libelf_ar.c | 43 | ||||
-rw-r--r-- | lib/libelf/libelf_convert.m4 | 13 | ||||
-rw-r--r-- | lib/libelf/libelf_ehdr.c | 11 | ||||
-rw-r--r-- | lib/libelf/libelf_extended.c | 12 | ||||
-rw-r--r-- | lib/libelf/libelf_memory.c | 4 | ||||
-rw-r--r-- | lib/libelf/libelf_phdr.c | 7 |
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); |