Mercurial > illumos > illumos-gate
changeset 3656:6ef316e5135c
6451309 mdb(1) dumps core on exitting due to a heap corruption in fake_elf()
author | jj204856 |
---|---|
date | Thu, 15 Feb 2007 07:08:19 -0800 |
parents | bf932d11a0cb |
children | 52fa1667b7c1 |
files | usr/src/lib/libproc/common/Psymtab_machelf32.c |
diffstat | 1 files changed, 44 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libproc/common/Psymtab_machelf32.c Wed Feb 14 20:19:07 2007 -0800 +++ b/usr/src/lib/libproc/common/Psymtab_machelf32.c Thu Feb 15 07:08:19 2007 -0800 @@ -186,6 +186,25 @@ #define SH_ADDRALIGN 4 #endif +/* + * This is the smallest number of PLT relocation entries allowed in a proper + * .plt section. + */ +#ifdef __sparc +#define PLTREL_MIN_ENTRIES 4 /* SPARC psABI 3.0 and SCD 2.4 */ +#else +#ifdef __lint +/* + * On x86, lint would complain about unsigned comparison with + * PLTREL_MIN_ENTRIES. This define fakes up the value of PLTREL_MIN_ENTRIES + * and silences lint. On SPARC, there is no such issue. + */ +#define PLTREL_MIN_ENTRIES 1 +#else +#define PLTREL_MIN_ENTRIES 0 +#endif +#endif + #ifdef _ELF64 Elf * fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, @@ -392,11 +411,20 @@ size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val; if (d[DI_PLTREL]->d_un.d_val == DT_RELA) { - uint_t ndx = pltrelsz / sizeof (Rela) - 2; + uint_t entries = pltrelsz / sizeof (Rela); Rela r[2]; - if (Pread(P, r, sizeof (r), jmprel + - sizeof (r[0]) * ndx) != sizeof (r)) { + if (entries < PLTREL_MIN_ENTRIES) { + dprintf("too few PLT relocation entries " + "(found %d, expected at least %d)\n", + entries, PLTREL_MIN_ENTRIES); + goto bad; + } + if (entries < PLTREL_MIN_ENTRIES + 2) + goto done_with_plt; + + if (Pread(P, r, sizeof (r), jmprel + sizeof (r[0]) * + entries - sizeof (r)) != sizeof (r)) { dprintf("Pread of DT_RELA failed\n"); goto bad; } @@ -405,11 +433,20 @@ ult = r[1].r_offset; } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) { - uint_t ndx = pltrelsz / sizeof (Rel) - 2; + uint_t entries = pltrelsz / sizeof (Rel); Rel r[2]; - if (Pread(P, r, sizeof (r), jmprel + - sizeof (r[0]) * ndx) != sizeof (r)) { + if (entries < PLTREL_MIN_ENTRIES) { + dprintf("too few PLT relocation entries " + "(found %d, expected at least %d)\n", + entries, PLTREL_MIN_ENTRIES); + goto bad; + } + if (entries < PLTREL_MIN_ENTRIES + 2) + goto done_with_plt; + + if (Pread(P, r, sizeof (r), jmprel + sizeof (r[0]) * + entries - sizeof (r)) != sizeof (r)) { dprintf("Pread of DT_REL failed\n"); goto bad; } @@ -431,6 +468,7 @@ size += sizeof (Shdr); size += roundup(pltsz, SH_ADDRALIGN); } +done_with_plt: if ((elfdata = calloc(1, size)) == NULL) goto bad;