diff options
Diffstat (limited to 'libelf')
46 files changed, 421 insertions, 215 deletions
diff --git a/libelf/_libelf.h b/libelf/_libelf.h index 26f17276b170..f826d1c360a5 100644 --- a/libelf/_libelf.h +++ b/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 3632 2018-10-10 21:12:43Z jkoshy $ + * $Id: _libelf.h 3738 2019-05-05 21:49:06Z jkoshy $ */ #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 */ /* @@ -226,7 +226,7 @@ size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version); void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count); Elf *_libelf_open_object(int _fd, Elf_Cmd _c, int _reporterror); struct _Libelf_Data *_libelf_release_data(struct _Libelf_Data *_d); -Elf *_libelf_release_elf(Elf *_e); +void _libelf_release_elf(Elf *_e); Elf_Scn *_libelf_release_scn(Elf_Scn *_s); int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum); int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum); diff --git a/libelf/_libelf_config.h b/libelf/_libelf_config.h index d70c04f97098..f28dc8ddf24e 100644 --- a/libelf/_libelf_config.h +++ b/libelf/_libelf_config.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _libelf_config.h 3566 2017-08-31 02:28:40Z emaste $ + * $Id: _libelf_config.h 3764 2019-06-28 21:44:46Z emaste $ */ #if defined(__APPLE__) || defined(__DragonFly__) @@ -103,6 +103,12 @@ #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS64 +#elif defined(__riscv64) + +#define LIBELF_ARCH EM_RISCV +#define LIBELF_BYTEORDER ELFDATA2LSB +#define LIBELF_CLASS ELFCLASS64 + #elif defined(__sparc__) #define LIBELF_ARCH EM_SPARCV9 diff --git a/libelf/elf.3 b/libelf/elf.3 index 269725a09ac8..7e1d3cb9a5ed 100644 --- a/libelf/elf.3 +++ b/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 3643 2018-10-14 21:09:24Z jkoshy $ +.\" $Id: elf.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd October 10, 2018 +.Dd June 12, 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. @@ -608,8 +615,11 @@ descriptor itself. .Xr ar 5 , .Xr elf 5 .Sh HISTORY -The original ELF(3) API was developed for Unix System V. -The current implementation of the ELF(3) API appeared in +The original +.Nm +API was developed for +.At V . +The current implementation of the API appeared in .Fx 7.0 . .Sh AUTHORS The ELF library was written by diff --git a/libelf/elf_data.c b/libelf/elf_data.c index bab70d003cee..6c6acb1441b0 100644 --- a/libelf/elf_data.c +++ b/libelf/elf_data.c @@ -32,7 +32,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: elf_data.c 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: elf_data.c 3732 2019-04-22 11:08:38Z jkoshy $"); 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); } @@ -116,7 +118,8 @@ elf_getdata(Elf_Scn *s, Elf_Data *ed) count = (size_t) (sh_size / fsz); - msz = _libelf_msize(elftype, elfclass, e->e_version); + if ((msz = _libelf_msize(elftype, elfclass, e->e_version)) == 0) + return (NULL); if (count > 0 && msz > SIZE_MAX / count) { LIBELF_SET_ERROR(RANGE, 0); @@ -215,7 +218,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 +256,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/libelf/elf_end.c b/libelf/elf_end.c index 3f32ebbee8ec..ed0c3ef845a9 100644 --- a/libelf/elf_end.c +++ b/libelf/elf_end.c @@ -34,7 +34,7 @@ #include <sys/mman.h> #endif -ELFTC_VCSID("$Id: elf_end.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: elf_end.c 3738 2019-05-05 21:49:06Z jkoshy $"); int elf_end(Elf *e) @@ -81,14 +81,14 @@ 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 } sv = e; if ((e = e->e_parent) != NULL) e->e_u.e_ar.e_nchildren--; - sv = _libelf_release_elf(sv); + _libelf_release_elf(sv); } return (0); diff --git a/libelf/elf_flagdata.3 b/libelf/elf_flagdata.3 index c210e4a56971..997da1e570be 100644 --- a/libelf/elf_flagdata.3 +++ b/libelf/elf_flagdata.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elf_flagdata.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: elf_flagdata.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd December 3, 2011 +.Dd June 12, 2019 .Dt ELF_FLAGDATA 3 .Os .Sh NAME @@ -34,7 +34,7 @@ .Nm elf_flagphdr , .Nm elf_flagscn , .Nm elf_flagshdr -.Nd manipulate flags associated with ELF(3) data structures +.Nd manipulate flags associated with ELF data structures .Sh LIBRARY .Lb libelf .Sh SYNOPSIS @@ -65,7 +65,9 @@ and .Ar scn denote the data structures whose flags need to be changed. These values should have been returned by prior calls to -functions in the ELF(3) API set: +functions in the +.Xr elf 3 +API set: .Bl -bullet -compact .It Argument @@ -175,7 +177,9 @@ function and the .Dv ELF_F_ARCHIVE and .Dv ELF_F_ARCHIVE_SYSV -flags are an extension to the ELF(3) API. +flags are an extension to the +.Xr elf 3 +API. .Sh ERRORS These functions may fail with the following errors: .Bl -tag -width "[ELF_E_RESOURCE]" diff --git a/libelf/elf_getdata.3 b/libelf/elf_getdata.3 index b287a25a00bc..66a6ef4fa9dd 100644 --- a/libelf/elf_getdata.3 +++ b/libelf/elf_getdata.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elf_getdata.3 3643 2018-10-14 21:09:24Z jkoshy $ +.\" $Id: elf_getdata.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd January 26, 2011 +.Dd April 22, 2019 .Dt ELF_GETDATA 3 .Os .Sh NAME @@ -214,7 +214,12 @@ is incorrect. .It Bq Er ELF_E_UNIMPL The section type associated with section .Ar scn -is currently unsupported by the library. +is not supported. +.It Bq Er ELF_E_VERSION +Section +.Ar scn +was associated with an ELF object with an unsupported +version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/elf_getident.c b/libelf/elf_getident.c index a69139c932cf..1196a76329f6 100644 --- a/libelf/elf_getident.c +++ b/libelf/elf_getident.c @@ -30,7 +30,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: elf_getident.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: elf_getident.c 3712 2019-03-16 22:23:34Z jkoshy $"); 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/libelf/elf_next.3 b/libelf/elf_next.3 index 0c2d92d67e2d..1ef02a9851b9 100644 --- a/libelf/elf_next.3 +++ b/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 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: elf_next.3 3698 2019-02-28 06:34:42Z jkoshy $ .\" -.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/libelf/elf_next.c b/libelf/elf_next.c index 4c33714f291a..dd5a93e4ed1d 100644 --- a/libelf/elf_next.c +++ b/libelf/elf_next.c @@ -30,7 +30,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: elf_next.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: elf_next.c 3710 2019-03-12 09:42:35Z jkoshy $"); 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/libelf/elf_open.3 b/libelf/elf_open.3 index acfbe8bc1cfd..054036a24935 100644 --- a/libelf/elf_open.3 +++ b/libelf/elf_open.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elf_open.3 3643 2018-10-14 21:09:24Z jkoshy $ +.\" $Id: elf_open.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd May 31, 2012 +.Dd June 12, 2019 .Dt ELF_OPEN 3 .Os .Sh NAME @@ -43,7 +43,9 @@ The functions .Fn elf_open and .Fn elf_openmemory -are extensions to the ELF(3) API, for the internal use of the +are extensions to the +.Xr elf 3 +API, for the internal use of the Elftoolchain project. Portable applications should not use these functions. .Pp @@ -71,7 +73,9 @@ specifies the size of the memory area in bytes. The function returns a pointer to a ELF descriptor if successful, or NULL if an error occurred. .Sh COMPATIBILITY -These functions are non-standard extensions to the ELF(3) API set. +These functions are non-standard extensions to the +.Xr elf 3 +API set. .Pp The behavior of these functions differs from their counterparts .Xr elf_begin 3 diff --git a/libelf/elf_rand.c b/libelf/elf_rand.c index eb2c9eaa2c1a..ac3bd0bc60e0 100644 --- a/libelf/elf_rand.c +++ b/libelf/elf_rand.c @@ -29,16 +29,25 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: elf_rand.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: elf_rand.c 3716 2019-03-18 22:01:01Z jkoshy $"); off_t elf_rand(Elf *ar, off_t offset) { struct ar_hdr *arh; + off_t offset_of_member; if (ar == NULL || ar->e_kind != ELF_K_AR || (offset & 1) || offset < SARMAG || - (size_t) offset + sizeof(struct ar_hdr) >= ar->e_rawsize) { + offset >= ar->e_rawsize) { + LIBELF_SET_ERROR(ARGUMENT, 0); + return 0; + } + + offset_of_member = offset + (off_t) sizeof(struct ar_hdr); + + if (offset_of_member <= 0 || /* Numeric overflow. */ + offset_of_member >= ar->e_rawsize) { LIBELF_SET_ERROR(ARGUMENT, 0); return 0; } diff --git a/libelf/elf_rawfile.c b/libelf/elf_rawfile.c index f63982fb0b4b..97abf06a2267 100644 --- a/libelf/elf_rawfile.c +++ b/libelf/elf_rawfile.c @@ -28,15 +28,13 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: elf_rawfile.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: elf_rawfile.c 3712 2019-03-16 22:23:34Z jkoshy $"); 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/libelf/elf_scn.c b/libelf/elf_scn.c index b72fef66c46b..f702474f35b2 100644 --- a/libelf/elf_scn.c +++ b/libelf/elf_scn.c @@ -36,7 +36,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: elf_scn.c 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: elf_scn.c 3712 2019-03-16 22:23:34Z jkoshy $"); /* * 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/libelf/elf_update.3 b/libelf/elf_update.3 index b6419cf9bf53..b87ab1640d1f 100644 --- a/libelf/elf_update.3 +++ b/libelf/elf_update.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elf_update.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: elf_update.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 14, 2011 +.Dd April 22, 2019 .Dt ELF_UPDATE 3 .Os .Sh NAME @@ -345,6 +345,10 @@ operation was requested after a prior call to disassociated the ELF descriptor .Ar elf from its underlying file. +.It Bq Er ELF_E_UNIMPL +Argument +.Ar elf +contained a section with an unsupported ELF type. .It Bq Er ELF_E_VERSION Argument .Ar elf diff --git a/libelf/elf_update.c b/libelf/elf_update.c index 25fa98d0bb12..d99a7bf937c6 100644 --- a/libelf/elf_update.c +++ b/libelf/elf_update.c @@ -41,7 +41,7 @@ #include <sys/mman.h> #endif -ELFTC_VCSID("$Id: elf_update.c 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: elf_update.c 3763 2019-06-28 21:43:27Z emaste $"); /* * 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); } @@ -222,10 +222,16 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc) } /* + * The data buffer's ELF type, ELF class and ELF version + * should be supported. + */ + if ((msz = _libelf_msize(d->d_type, ec, e->e_version)) == 0) + return (0); + + /* * The buffer's size should be a multiple of the * memory size of the underlying type. */ - msz = _libelf_msize(d->d_type, ec, e->e_version); if (d->d_size % msz) { LIBELF_SET_ERROR(DATA, 0); return (0); @@ -800,7 +806,8 @@ _libelf_write_scn(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) d = &ld->d_data; - msz = _libelf_msize(d->d_type, ec, e->e_version); + if ((msz = _libelf_msize(d->d_type, ec, e->e_version)) == 0) + return ((off_t) -1); if ((uint64_t) rc < sh_off + d->d_off) (void) memset(nf + rc, @@ -812,6 +819,7 @@ _libelf_write_scn(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) assert(d->d_buf != NULL); assert(d->d_version == e->e_version); assert(d->d_size % msz == 0); + assert(msz != 0); nobjects = (size_t) (d->d_size / msz); @@ -851,7 +859,8 @@ _libelf_write_ehdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) assert(ehdr != NULL); fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); - msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_EHDR, ec, e->e_version)) == 0) + return ((off_t) -1); em = _libelf_elfmachine(e); @@ -885,15 +894,17 @@ _libelf_write_phdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; Elf_Data dst, src; - size_t fsz, phnum; + size_t fsz, msz, phnum; uint64_t phoff; assert(ex->ex_type == ELF_EXTENT_PHDR); ec = e->e_class; + ehdr = _libelf_ehdr(e, ec, 0); - phnum = e->e_u.e_elf.e_nphdr; + assert(ehdr != NULL); + phnum = e->e_u.e_elf.e_nphdr; assert(phnum > 0); if (ec == ELFCLASS32) { @@ -913,14 +924,15 @@ _libelf_write_phdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) (void) memset(&dst, 0, sizeof(dst)); (void) memset(&src, 0, sizeof(src)); + if ((msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version)) == 0) + return ((off_t) -1); fsz = _libelf_fsize(ELF_T_PHDR, ec, e->e_version, phnum); assert(fsz > 0); src.d_buf = _libelf_getphdr(e, ec); src.d_version = dst.d_version = e->e_version; src.d_type = ELF_T_PHDR; - src.d_size = phnum * _libelf_msize(ELF_T_PHDR, ec, - e->e_version); + src.d_size = phnum * msz; dst.d_size = fsz; dst.d_buf = nf + ex->ex_start; @@ -945,13 +957,16 @@ _libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) uint64_t shoff; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; - size_t fsz, nscn; + size_t fsz, msz, nscn; Elf_Data dst, src; assert(ex->ex_type == ELF_EXTENT_SHDR); ec = e->e_class; + ehdr = _libelf_ehdr(e, ec, 0); + assert(ehdr != NULL); + nscn = e->e_u.e_elf.e_nscn; if (ec == ELFCLASS32) { @@ -971,8 +986,11 @@ _libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) (void) memset(&dst, 0, sizeof(dst)); (void) memset(&src, 0, sizeof(src)); + if ((msz = _libelf_msize(ELF_T_SHDR, ec, e->e_version)) == 0) + return ((off_t) -1); + src.d_type = ELF_T_SHDR; - src.d_size = _libelf_msize(ELF_T_SHDR, ec, e->e_version); + src.d_size = msz; src.d_version = dst.d_version = e->e_version; fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); @@ -1084,7 +1102,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; } @@ -1109,12 +1127,14 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents) assert((e->e_flags & LIBELF_F_RAWFILE_MALLOC) || (e->e_flags & LIBELF_F_RAWFILE_MMAP)); if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) { + assert((e->e_flags & LIBELF_F_RAWFILE_MMAP) == 0); free(e->e_rawfile); e->e_rawfile = newfile; newfile = NULL; } #if ELFTC_HAVE_MMAP else if (e->e_flags & LIBELF_F_RAWFILE_MMAP) { + assert((e->e_flags & LIBELF_F_RAWFILE_MALLOC) == 0); if ((e->e_rawfile = mmap(NULL, (size_t) newsize, PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) == MAP_FAILED) { @@ -1125,7 +1145,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/libelf/gelf.3 b/libelf/gelf.3 index 704ae154700f..d703c1b3f65e 100644 --- a/libelf/gelf.3 +++ b/libelf/gelf.3 @@ -21,13 +21,13 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf.3 3643 2018-10-14 21:09:24Z jkoshy $ +.\" $Id: gelf.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd September 1, 2006 +.Dd June 12, 2019 .Dt GELF 3 .Os .Sh NAME -.Nm GElf +.Nm gelf .Nd class-independent API for ELF manipulation .Sh LIBRARY .Lb libelf @@ -192,7 +192,10 @@ Copy back an ELF symbol table entry. .Xr elf 3 , .Xr elf 5 .Sh HISTORY -The GELF(3) API first appeared in System V Release 4. +The +.Nm +API first appeared in +.At V.4 . This implementation of the API first appeared in .Fx 7.0 . .Sh AUTHORS diff --git a/libelf/gelf_cap.c b/libelf/gelf_cap.c index f509c69c2ba5..6ebdd97a0c52 100644 --- a/libelf/gelf_cap.c +++ b/libelf/gelf_cap.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_cap.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_cap.c 3732 2019-04-22 11:08:38Z jkoshy $"); GElf_Cap * gelf_getcap(Elf_Data *ed, int ndx, GElf_Cap *dst) @@ -67,9 +67,8 @@ gelf_getcap(Elf_Data *ed, int ndx, GElf_Cap *dst) return (NULL); } - msz = _libelf_msize(ELF_T_CAP, ec, e->e_version); - - assert(msz > 0); + if ((msz = _libelf_msize(ELF_T_CAP, ec, e->e_version)) == 0) + return (NULL); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); @@ -127,8 +126,8 @@ gelf_update_cap(Elf_Data *ed, int ndx, GElf_Cap *gc) return (0); } - msz = _libelf_msize(ELF_T_CAP, ec, e->e_version); - assert(msz > 0); + if ((msz = _libelf_msize(ELF_T_CAP, ec, e->e_version)) == 0) + return (0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); diff --git a/libelf/gelf_dyn.c b/libelf/gelf_dyn.c index 74233094bf6c..1c8b133ceada 100644 --- a/libelf/gelf_dyn.c +++ b/libelf/gelf_dyn.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_dyn.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_dyn.c 3732 2019-04-22 11:08:38Z jkoshy $"); GElf_Dyn * gelf_getdyn(Elf_Data *ed, int ndx, GElf_Dyn *dst) @@ -67,9 +67,9 @@ gelf_getdyn(Elf_Data *ed, int ndx, GElf_Dyn *dst) return (NULL); } - msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_DYN, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -127,9 +127,9 @@ gelf_update_dyn(Elf_Data *ed, int ndx, GElf_Dyn *ds) return (0); } - msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_DYN, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { diff --git a/libelf/gelf_getcap.3 b/libelf/gelf_getcap.3 index 276933a8365a..d1c1c2c76c1d 100644 --- a/libelf/gelf_getcap.3 +++ b/libelf/gelf_getcap.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getcap.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getcap.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETCAP 3 .Os .Sh NAME @@ -113,6 +113,12 @@ was not associated with a section of type .Dv SHT_SUNW_cap . .It Bq Er ELF_E_RANGE A value was not representable in the target type. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getdyn.3 b/libelf/gelf_getdyn.3 index a4e51ecd0ee2..1db1a5a5e918 100644 --- a/libelf/gelf_getdyn.3 +++ b/libelf/gelf_getdyn.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getdyn.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getdyn.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETDYN 3 .Os .Sh NAME @@ -115,6 +115,13 @@ was not associated with a section of type .Dv SHT_DYNAMIC . .It Bq Er ELF_E_RANGE A value was not representable in the target type. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. +.El .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getmove.3 b/libelf/gelf_getmove.3 index 64c52d9682ed..7f10d2c0d1ca 100644 --- a/libelf/gelf_getmove.3 +++ b/libelf/gelf_getmove.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getmove.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getmove.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETMOVE 3 .Os .Sh NAME @@ -112,6 +112,12 @@ Data descriptor was not associated with a section containing move information. .It Bq Er ELF_E_RANGE A value was not representable in the target type. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getrel.3 b/libelf/gelf_getrel.3 index c21be0da8b46..056bf1a67fcc 100644 --- a/libelf/gelf_getrel.3 +++ b/libelf/gelf_getrel.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getrel.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getrel.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETREL 3 .Os .Sh NAME @@ -113,6 +113,12 @@ was not associated with a section of type .Dv SHT_REL . .It Bq Er ELF_E_RANGE A value was not representable in the target type. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getrela.3 b/libelf/gelf_getrela.3 index 946482e605ef..0eb0ab31ce10 100644 --- a/libelf/gelf_getrela.3 +++ b/libelf/gelf_getrela.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getrela.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getrela.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETRELA 3 .Os .Sh NAME @@ -113,6 +113,12 @@ was not associated with a section of type .Dv SHT_RELA . .It Bq Er ELF_E_RANGE A value was not representable in the target type. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getsym.3 b/libelf/gelf_getsym.3 index a139c152d15d..e2bbc9eb2f49 100644 --- a/libelf/gelf_getsym.3 +++ b/libelf/gelf_getsym.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getsym.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getsym.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETSYM 3 .Os .Sh NAME @@ -115,6 +115,12 @@ Data descriptor was not associated with a section containing symbol information. .It Bq Er ELF_E_RANGE A value was not representable in the target type. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getsyminfo.3 b/libelf/gelf_getsyminfo.3 index 0f602c289795..71a69b87cff1 100644 --- a/libelf/gelf_getsyminfo.3 +++ b/libelf/gelf_getsyminfo.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getsyminfo.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getsyminfo.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd August 29, 2006 +.Dd April 22, 2019 .Dt GELF_GETSYMINFO 3 .Os .Sh NAME @@ -105,6 +105,12 @@ descriptor. Data descriptor .Ar data was not associated with a section containing symbol information. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptor denoted by argument +.Ar data +is associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_getsymshndx.3 b/libelf/gelf_getsymshndx.3 index 595472a429e3..66b3efd3d89e 100644 --- a/libelf/gelf_getsymshndx.3 +++ b/libelf/gelf_getsymshndx.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_getsymshndx.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_getsymshndx.3 3734 2019-04-22 14:10:49Z jkoshy $ .\" -.Dd November 5, 2006 +.Dd April 22, 2019 .Dt GELF_GETSYMSHNDX 3 .Os .Sh NAME @@ -152,6 +152,14 @@ Data descriptor and .Ar xndxdata were associated with different ELF objects. +.It Bq Er ELF_E_VERSION +The +.Vt Elf_Data +descriptors denoted by arguments +.Ar symdata +and +.Ar xndxdata +are associated with an ELF object with an unsupported version. .El .Sh SEE ALSO .Xr elf 3 , diff --git a/libelf/gelf_move.c b/libelf/gelf_move.c index 2ec8f251f8fa..e5187bf05cf9 100644 --- a/libelf/gelf_move.c +++ b/libelf/gelf_move.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_move.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_move.c 3732 2019-04-22 11:08:38Z jkoshy $"); GElf_Move * gelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst) @@ -67,9 +67,9 @@ gelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst) return (NULL); } - msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -130,9 +130,9 @@ gelf_update_move(Elf_Data *ed, int ndx, GElf_Move *gm) return (0); } - msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { diff --git a/libelf/gelf_newehdr.3 b/libelf/gelf_newehdr.3 index 38698c32e8b0..5a15ea7d76c6 100644 --- a/libelf/gelf_newehdr.3 +++ b/libelf/gelf_newehdr.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_newehdr.3 3643 2018-10-14 21:09:24Z jkoshy $ +.\" $Id: gelf_newehdr.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd October 22, 2007 +.Dd June 12, 2019 .Dt GELF_NEWEHDR 3 .Os .Sh NAME @@ -134,7 +134,9 @@ The function uses a type of .Ft "void *" for its returned value. -This differs from some other implementations of the ELF(3) API, which use an +This differs from some other implementations of the +.Xr elf 3 +API, which use an .Ft "unsigned long" return type. .Sh ERRORS diff --git a/libelf/gelf_newphdr.3 b/libelf/gelf_newphdr.3 index a881aab4dd6e..01d6cbc38118 100644 --- a/libelf/gelf_newphdr.3 +++ b/libelf/gelf_newphdr.3 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: gelf_newphdr.3 3639 2018-10-14 14:07:02Z jkoshy $ +.\" $Id: gelf_newphdr.3 3743 2019-06-12 19:36:30Z jkoshy $ .\" -.Dd October 22, 2007 +.Dd June 12, 2019 .Dt GELF_NEWPHDR 3 .Os .Sh NAME @@ -103,7 +103,9 @@ The function uses a type of .Ft "void *" for its returned value. -This differs from some other implementations of the ELF(3) API, which use an +This differs from some other implementations of the +.Xr elf 3 +API, which use an .Ft "unsigned long" return type. .Sh ERRORS diff --git a/libelf/gelf_rel.c b/libelf/gelf_rel.c index 02a613383dfb..54a1002c8679 100644 --- a/libelf/gelf_rel.c +++ b/libelf/gelf_rel.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_rel.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_rel.c 3739 2019-05-06 05:18:15Z jkoshy $"); GElf_Rel * gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst) @@ -67,9 +67,9 @@ gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst) return (NULL); } - msz = _libelf_msize(ELF_T_REL, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_REL, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -129,9 +129,9 @@ gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr) return (0); } - msz = _libelf_msize(ELF_T_REL, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_REL, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -144,7 +144,7 @@ gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr) LIBELF_COPY_U32(rel32, dr, r_offset); - if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) || + if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0U) || ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) { LIBELF_SET_ERROR(RANGE, 0); return (0); diff --git a/libelf/gelf_rela.c b/libelf/gelf_rela.c index d485ab909299..0fa20a515292 100644 --- a/libelf/gelf_rela.c +++ b/libelf/gelf_rela.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_rela.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_rela.c 3739 2019-05-06 05:18:15Z jkoshy $"); GElf_Rela * gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst) @@ -67,9 +67,9 @@ gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst) return (NULL); } - msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_RELA, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -130,9 +130,9 @@ gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr) return (0); } - msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_RELA, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -145,7 +145,7 @@ gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr) LIBELF_COPY_U32(rela32, dr, r_offset); - if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) || + if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0U) || ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) { LIBELF_SET_ERROR(RANGE, 0); return (0); diff --git a/libelf/gelf_sym.c b/libelf/gelf_sym.c index ecd85fceefb4..c5f4484d56e6 100644 --- a/libelf/gelf_sym.c +++ b/libelf/gelf_sym.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_sym.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_sym.c 3732 2019-04-22 11:08:38Z jkoshy $"); GElf_Sym * gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst) @@ -67,9 +67,9 @@ gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst) return (NULL); } - msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_SYM, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -129,9 +129,9 @@ gelf_update_sym(Elf_Data *ed, int ndx, GElf_Sym *gs) return (0); } - msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_SYM, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { diff --git a/libelf/gelf_syminfo.c b/libelf/gelf_syminfo.c index f6d7b6c367fa..9f3cd0e6f701 100644 --- a/libelf/gelf_syminfo.c +++ b/libelf/gelf_syminfo.c @@ -29,7 +29,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_syminfo.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_syminfo.c 3732 2019-04-22 11:08:38Z jkoshy $"); GElf_Syminfo * gelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst) @@ -65,9 +65,9 @@ gelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst) return (NULL); } - msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { @@ -126,9 +126,9 @@ gelf_update_syminfo(Elf_Data *ed, int ndx, GElf_Syminfo *gs) return (0); } - msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { diff --git a/libelf/gelf_symshndx.c b/libelf/gelf_symshndx.c index b490aa2bb11f..4a48a43d12b8 100644 --- a/libelf/gelf_symshndx.c +++ b/libelf/gelf_symshndx.c @@ -29,7 +29,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_symshndx.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: gelf_symshndx.c 3732 2019-04-22 11:08:38Z jkoshy $"); GElf_Sym * gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst, @@ -69,9 +69,9 @@ gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst, return (NULL); } - msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_WORD, ec, e->e_version)) == 0) + return (NULL); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= id->d_size) { @@ -121,9 +121,9 @@ gelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs, return (0); } - msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); + if ((msz = _libelf_msize(ELF_T_WORD, ec, e->e_version)) == 0) + return (0); - assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= id->d_size) { diff --git a/libelf/libelf_allocate.c b/libelf/libelf_allocate.c index 0a74facc9fc4..2146b05141fd 100644 --- a/libelf/libelf_allocate.c +++ b/libelf/libelf_allocate.c @@ -36,33 +36,26 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_allocate.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: libelf_allocate.c 3738 2019-05-05 21:49:06Z jkoshy $"); 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,31 +76,25 @@ _libelf_init_elf(Elf *e, Elf_Kind kind) } } -#define FREE(P) do { \ - if (P) \ - free(P); \ - } while (0) - - -Elf * +void _libelf_release_elf(Elf *e) { Elf_Arhdr *arh; 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); } @@ -127,8 +114,6 @@ _libelf_release_elf(Elf *e) } free(e); - - return (NULL); } struct _Libelf_Data * diff --git a/libelf/libelf_ar.c b/libelf/libelf_ar.c index 8fce7419726e..6634d2c73c33 100644 --- a/libelf/libelf_ar.c +++ b/libelf/libelf_ar.c @@ -33,7 +33,7 @@ #include "_libelf.h" #include "_libelf_ar.h" -ELFTC_VCSID("$Id: libelf_ar.c 3446 2016-05-03 01:31:17Z emaste $"); +ELFTC_VCSID("$Id: libelf_ar.c 3712 2019-03-16 22:23:34Z jkoshy $"); #define LIBELF_NALLOC_SIZE 16 @@ -123,8 +123,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); @@ -199,8 +207,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; @@ -217,6 +225,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); /* @@ -229,6 +248,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. */ @@ -286,7 +316,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; @@ -343,7 +374,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/libelf/libelf_convert.m4 b/libelf/libelf_convert.m4 index 04adeb3114a7..bb601ad92841 100644 --- a/libelf/libelf_convert.m4 +++ b/libelf/libelf_convert.m4 @@ -30,7 +30,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_convert.m4 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_convert.m4 3712 2019-03-16 22:23:34Z jkoshy $"); /* WARNING: GENERATED FROM __file__. */ @@ -820,7 +820,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++) { @@ -901,7 +901,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) @@ -1078,13 +1078,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/libelf/libelf_data.c b/libelf/libelf_data.c index fcffd8bd9d1c..968394d9bf9a 100644 --- a/libelf/libelf_data.c +++ b/libelf/libelf_data.c @@ -28,7 +28,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_data.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: libelf_data.c 3737 2019-05-05 14:49:50Z jkoshy $"); int _libelf_xlate_shtype(uint32_t sht) @@ -89,8 +89,14 @@ _libelf_xlate_shtype(uint32_t sht) * OS, processor and user-defined section types) are * legal, but since we do not know anything more about * their semantics, we return a type of ELF_T_BYTE. + * + * The ELF specification uses 32 bit unsigned values for + * denoting section types, and defines SHT_HIUSER to be + * 0xFFFFFFFFUL (i.e., UINT32_MAX). Consequently, we only + * need to check that 'sht' is greater than or equal to + * SHT_LOOS. */ - if (sht >= SHT_LOOS && sht <= SHT_HIUSER) + if (sht >= SHT_LOOS) return (ELF_T_BYTE); /* diff --git a/libelf/libelf_ehdr.c b/libelf/libelf_ehdr.c index 38e4e74e14d2..e06c03355038 100644 --- a/libelf/libelf_ehdr.c +++ b/libelf/libelf_ehdr.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_ehdr.c 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_ehdr.c 3732 2019-04-22 11:08:38Z jkoshy $"); /* * 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,14 +143,13 @@ _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); } - msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT); - - assert(msz > 0); + if ((msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT)) == 0) + return (NULL); if ((ehdr = calloc((size_t) 1, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); diff --git a/libelf/libelf_extended.c b/libelf/libelf_extended.c index 96765a8293e1..59376e430861 100644 --- a/libelf/libelf_extended.c +++ b/libelf/libelf_extended.c @@ -29,7 +29,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_extended.c 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: libelf_extended.c 3712 2019-03-16 22:23:34Z jkoshy $"); /* * 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/libelf/libelf_memory.c b/libelf/libelf_memory.c index cb8e8f20438a..12ab12aed70e 100644 --- a/libelf/libelf_memory.c +++ b/libelf/libelf_memory.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_memory.c 3013 2014-03-23 06:16:59Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_memory.c 3738 2019-05-05 21:49:06Z jkoshy $"); /* * 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 && \ @@ -78,7 +78,7 @@ _libelf_memory(unsigned char *image, size_t sz, int reporterror) if (error != ELF_E_NONE) { if (reporterror) { LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0); - (void) _libelf_release_elf(e); + _libelf_release_elf(e); return (NULL); } } else { diff --git a/libelf/libelf_msize.m4 b/libelf/libelf_msize.m4 index 179880c43278..2751f5be8b82 100644 --- a/libelf/libelf_msize.m4 +++ b/libelf/libelf_msize.m4 @@ -30,7 +30,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_msize.m4 3174 2015-03-27 17:13:41Z emaste $"); +ELFTC_VCSID("$Id: libelf_msize.m4 3732 2019-04-22 11:08:38Z jkoshy $"); /* WARNING: GENERATED FROM __file__. */ @@ -87,6 +87,14 @@ static struct msize msize[ELF_T_NUM] = { MSIZES(ELF_TYPE_LIST) }; +/* + * Returns the memory size of the specified ELF type 't' of ELF + * class 'ec' and ELF version 'version'. + * + * If the specified combination of ELF type, class, and version is + * unsupported then a value of 0 will be returned and the appropriate + * library error code set. + */ size_t _libelf_msize(Elf_Type t, int elfclass, unsigned int version) { @@ -102,5 +110,10 @@ _libelf_msize(Elf_Type t, int elfclass, unsigned int version) sz = (elfclass == ELFCLASS32) ? msize[t].msz32 : msize[t].msz64; + if (sz == 0) { + LIBELF_SET_ERROR(UNIMPL, 0); + return (0); + } + return (sz); } diff --git a/libelf/libelf_phdr.c b/libelf/libelf_phdr.c index 336ef3877f6f..5675a2e8c54c 100644 --- a/libelf/libelf_phdr.c +++ b/libelf/libelf_phdr.c @@ -31,7 +31,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_phdr.c 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_phdr.c 3732 2019-04-22 11:08:38Z jkoshy $"); void * _libelf_getphdr(Elf *e, int ec) @@ -77,14 +77,18 @@ _libelf_getphdr(Elf *e, int ec) assert(fsz > 0); - if ((uint64_t) e->e_rawsize < (phoff + fsz)) { + if (phoff + fsz < phoff) { /* Numeric overflow. */ LIBELF_SET_ERROR(HEADER, 0); return (NULL); } - msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT); + if ((uint64_t) e->e_rawsize < (phoff + fsz)) { + LIBELF_SET_ERROR(HEADER, 0); + return (NULL); + } - assert(msz > 0); + if ((msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT)) == 0) + return (NULL); if ((phdr = calloc(phnum, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); @@ -125,9 +129,8 @@ _libelf_newphdr(Elf *e, int ec, size_t count) assert(ec == ELFCLASS32 || ec == ELFCLASS64); assert(e->e_version == EV_CURRENT); - msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version); - - assert(msz > 0); + if ((msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version)) == 0) + return (NULL); newphdr = NULL; if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { diff --git a/libelf/libelf_xlate.c b/libelf/libelf_xlate.c index cfe6a0bdfdbd..7bb0e0f9d683 100644 --- a/libelf/libelf_xlate.c +++ b/libelf/libelf_xlate.c @@ -29,7 +29,7 @@ #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_xlate.c 3632 2018-10-10 21:12:43Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_xlate.c 3732 2019-04-22 11:08:38Z jkoshy $"); /* * Translate to/from the file representation of ELF objects. @@ -83,9 +83,8 @@ _libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, (src->d_type, (size_t) 1, src->d_version)) == 0) return (NULL); - msz = _libelf_msize(src->d_type, elfclass, src->d_version); - - assert(msz > 0); + if ((msz = _libelf_msize(src->d_type, elfclass, src->d_version)) == 0) + return (NULL); if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { LIBELF_SET_ERROR(DATA, 0); diff --git a/libelf/os.Linux.mk b/libelf/os.Linux.mk new file mode 100644 index 000000000000..2292b6ec5f02 --- /dev/null +++ b/libelf/os.Linux.mk @@ -0,0 +1,31 @@ +# Enable additional warnings. +CFLAGS+= -Wa,--fatal-warnings +CFLAGS+= -Wall +CFLAGS+= -Wcast-align +CFLAGS+= -Wcast-qual +CFLAGS+= -Wchar-subscripts +CFLAGS+= -Wconversion +CFLAGS+= -Werror +CFLAGS+= -Wextra +CFLAGS+= -Wformat=2 +CFLAGS+= -Winline +CFLAGS+= -Wmissing-prototypes +CFLAGS+= -Wnested-externs +CFLAGS+= -Wempty-body +CFLAGS+= -Wformat-y2k +CFLAGS+= -Wformat-zero-length +CFLAGS+= -Wpointer-sign +CFLAGS+= -Wpointer-to-int-cast +CFLAGS+= -Wsign-compare +CFLAGS+= -Wunused-const-variable +CFLAGS+= -Wunused-parameter +CFLAGS+= -Wold-style-definition +CFLAGS+= -Wpointer-arith +CFLAGS+= -Wredundant-decls +CFLAGS+= -Wreturn-type +CFLAGS+= -Wshadow +CFLAGS+= -Wstrict-prototypes +CFLAGS+= -Wstrict-overflow +CFLAGS+= -Wswitch +CFLAGS+= -Wunused-parameter +CFLAGS+= -Wwrite-strings |