summaryrefslogtreecommitdiff
path: root/libelf/elf_update.c
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2019-06-29 15:27:18 +0000
committerEd Maste <emaste@FreeBSD.org>2019-06-29 15:27:18 +0000
commita5b08c1484eac2c6a65e726f550b3189ff84c6c8 (patch)
tree01cd9d6d76e2c378b391422460c6f233ead08179 /libelf/elf_update.c
parent2b92b30119ed91ed88f102ba9ecc40cd1c046a65 (diff)
Notes
Diffstat (limited to 'libelf/elf_update.c')
-rw-r--r--libelf/elf_update.c46
1 files changed, 33 insertions, 13 deletions
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);