diff options
author | Cody Peter Mello <cody.mello@joyent.com> | 2019-03-04 18:03:47 +0000 |
---|---|---|
committer | Cody Peter Mello <melloc@writev.io> | 2019-03-04 21:29:03 +0000 |
commit | 31fd5d7bc7a22f5f61d4a1b782a407e05cf49ad1 (patch) | |
tree | fe62b30e1d4a58fefb5d0cddfde0694b41b8a393 /usr/src/uts/common/exec | |
parent | d959f82bb4585e1dbd808a8420514ca76a20b9e1 (diff) | |
download | illumos-joyent-31fd5d7bc7a22f5f61d4a1b782a407e05cf49ad1.tar.gz |
OS-7630 elfexec() should keep to unsigned types when processing PT_DYNAMIC
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/uts/common/exec')
-rw-r--r-- | usr/src/uts/common/exec/elf/elf.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/usr/src/uts/common/exec/elf/elf.c b/usr/src/uts/common/exec/elf/elf.c index 87bf950a30..0b4e70cad3 100644 --- a/usr/src/uts/common/exec/elf/elf.c +++ b/usr/src/uts/common/exec/elf/elf.c @@ -26,7 +26,7 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* - * Copyright (c) 2018, Joyent, Inc. + * Copyright (c) 2019, Joyent, Inc. */ #include <sys/types.h> @@ -377,16 +377,16 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap, Phdr *uphdr = NULL; Phdr *junk = NULL; size_t len; + size_t i; ssize_t phdrsize; int postfixsize = 0; - int i, hsize; + int hsize; Phdr *phdrp; Phdr *dataphdrp = NULL; Phdr *dtrphdr; Phdr *capphdr = NULL; Cap *cap = NULL; ssize_t capsize; - Dyn *dyn = NULL; int hasu = 0; int hasauxv = 0; int hasintp = 0; @@ -663,24 +663,30 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap, } /* If the binary has an explicit ASLR flag, it must be honoured */ - if ((dynamicphdr != NULL) && - (dynamicphdr->p_filesz > 0)) { - Dyn *dp; - off_t i = 0; + if ((dynamicphdr != NULL) && (dynamicphdr->p_filesz > 0)) { + const size_t dynfilesz = dynamicphdr->p_filesz; + const size_t dynoffset = dynamicphdr->p_offset; + Dyn *dyn, *dp; + + if (dynoffset > MAXOFFSET_T || + dynfilesz > MAXOFFSET_T || + dynoffset + dynfilesz > MAXOFFSET_T) { + uprintf("%s: cannot read full .dynamic section\n", + exec_file); + error = EINVAL; + goto out; + } #define DYN_STRIDE 100 - for (i = 0; i < dynamicphdr->p_filesz; - i += sizeof (*dyn) * DYN_STRIDE) { - int ndyns = (dynamicphdr->p_filesz - i) / sizeof (*dyn); - size_t dynsize; - - ndyns = MIN(DYN_STRIDE, ndyns); - dynsize = ndyns * sizeof (*dyn); + for (i = 0; i < dynfilesz; i += sizeof (*dyn) * DYN_STRIDE) { + const size_t remdyns = (dynfilesz - i) / sizeof (*dyn); + const size_t ndyns = MIN(DYN_STRIDE, remdyns); + const size_t dynsize = ndyns * sizeof (*dyn); dyn = kmem_alloc(dynsize, KM_SLEEP); if ((error = vn_rdwr(UIO_READ, vp, (caddr_t)dyn, - dynsize, (offset_t)(dynamicphdr->p_offset + i), + (ssize_t)dynsize, (offset_t)(dynoffset + i), UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid)) != 0) { uprintf("%s: cannot read .dynamic section\n", |