From 58b6f8de8862c9ccba763d3607afb5495727e4d6 Mon Sep 17 00:00:00 2001 From: norly Date: Sat, 23 Feb 2013 01:46:32 +0000 Subject: [PATCH] Add run-time sanity checks --- include/libelfu/lookup.h | 4 ++ include/libelfu/model.h | 7 ++- src/lookup/scnSize.c | 13 +++++ src/main.c | 3 ++ src/model/check.c | 104 +++++++++++++++++++++++++++++++++++++++ src/model/count.c | 6 +++ src/model/fromFile.c | 18 +++++-- src/model/section-name.c | 27 ++++++++++ 8 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 src/lookup/scnSize.c create mode 100644 src/model/check.c create mode 100644 src/model/section-name.c diff --git a/include/libelfu/lookup.h b/include/libelfu/lookup.h index 2cca5df..2506512 100644 --- a/include/libelfu/lookup.h +++ b/include/libelfu/lookup.h @@ -7,8 +7,12 @@ #include char* elfu_sectionName(Elf *e, Elf_Scn *scn); + Elf_Scn* elfu_sectionByName(Elf *e, char *name); + Elf_Scn* elfu_firstSectionInSegment(Elf *e, GElf_Phdr *phdr); Elf_Scn* elfu_lastSectionInSegment(Elf *e, GElf_Phdr *phdr); +size_t elfu_scnSizeFile(const GElf_Shdr *shdr); + #endif diff --git a/include/libelfu/model.h b/include/libelfu/model.h index 1b5f6b6..588d57a 100644 --- a/include/libelfu/model.h +++ b/include/libelfu/model.h @@ -37,8 +37,7 @@ typedef struct { CIRCLEQ_HEAD(ScnList, ElfuScn) scnList; CIRCLEQ_HEAD(PhdrList, ElfuPhdr) phdrList; - ElfuPhdr *entryBase; - GElf_Addr *entryOffs; + ElfuScn *shstrtab; } ElfuElf; @@ -46,6 +45,10 @@ typedef struct { size_t elfu_countSections(ElfuElf *me); size_t elfu_countPHDRs(ElfuElf *me); +char* elfu_modelScnName(ElfuElf *me, ElfuScn *ms); + +int elfu_modelCheck(ElfuElf *me); + ElfuPhdr* elfu_modelFromPhdr(GElf_Phdr *phdr); ElfuScn* elfu_modelFromSection(Elf_Scn *scn); ElfuElf* elfu_modelFromElf(Elf *e); diff --git a/src/lookup/scnSize.c b/src/lookup/scnSize.c new file mode 100644 index 0000000..2c65ca1 --- /dev/null +++ b/src/lookup/scnSize.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + + + +size_t elfu_scnSizeFile(const GElf_Shdr *shdr) +{ + assert(shdr); + + return shdr->sh_type == SHT_NOBITS ? 0 : shdr->sh_size; +} diff --git a/src/main.c b/src/main.c index 68becad..eaf2709 100644 --- a/src/main.c +++ b/src/main.c @@ -68,6 +68,9 @@ int main(int argc, char **argv) if (me) { printf("Model successfully loaded.\n"); + elfu_modelCheck(me); + printf("Model checked.\n"); + elfu_modelToElf(me, hOut.e); printf("Model converted to ELF, ready to be written.\n"); diff --git a/src/model/check.c b/src/model/check.c new file mode 100644 index 0000000..cd45f2d --- /dev/null +++ b/src/model/check.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include + + + +static int isOverlapping(size_t off1, size_t sz1, size_t off2, size_t sz2) +{ + size_t end1 = off1 + sz1; + size_t end2 = off2 + sz2; + + if (off2 >= off1 && off2 < end1) { + return 1; + } else if (off1 >= off2 && off1 < end2) { + return 1; + } else { + return 0; + } +} + + +static int cmpScnOffs(const void *ms1, const void *ms2) +{ + assert(ms1); + assert(ms2); + + ElfuScn *s1 = *(ElfuScn**)ms1; + ElfuScn *s2 = *(ElfuScn**)ms2; + + assert(s1); + assert(s2); + + + if (s1->shdr.sh_offset < s2->shdr.sh_offset) { + return -1; + } else if (s1->shdr.sh_offset == s2->shdr.sh_offset) { + return 0; + } else /* if (s1->shdr.sh_offset > s2->shdr.sh_offset) */ { + return 1; + } +} + + +int elfu_modelCheck(ElfuElf *me) +{ + ElfuScn *ms; + size_t numSecs; + ElfuScn **sortedSecs; + size_t i; + + /* Sort sections by offset in file */ + numSecs = elfu_countSections(me); + sortedSecs = malloc(numSecs * sizeof(*sortedSecs)); + if (!sortedSecs) { + fprintf(stderr, "elfu_check: Failed to allocate memory.\n"); + } + + i = 0; + CIRCLEQ_FOREACH(ms, &me->scnList, elem) { + sortedSecs[i] = ms; + i++; + } + assert(i = numSecs); + + qsort(sortedSecs, numSecs, sizeof(*sortedSecs), cmpScnOffs); + + + /* Check for overlapping sections */ + for (i = 0; i < numSecs - 1; i++) { + if (sortedSecs[i]->shdr.sh_offset + elfu_scnSizeFile(&sortedSecs[i]->shdr) + > sortedSecs[i+1]->shdr.sh_offset) { + fprintf(stderr, "elfu_check: Found overlapping sections: %s and %s.\n", + elfu_modelScnName(me, sortedSecs[i]), + elfu_modelScnName(me, sortedSecs[i+1])); + } + } + + + /* Check for sections overlapping with EHDR */ + for (i = 0; i < numSecs; i++) { + if (sortedSecs[i]->shdr.sh_offset < me->ehdr.e_ehsize) { + fprintf(stderr, "elfu_check: Found section overlapping with EHDR: %s.\n", + elfu_modelScnName(me, sortedSecs[i])); + } + } + + + /* Check for sections overlapping with PHDRs */ + for (i = 0; i < numSecs; i++) { + if (isOverlapping(sortedSecs[i]->shdr.sh_offset, + elfu_scnSizeFile(&sortedSecs[i]->shdr), + me->ehdr.e_phoff, + me->ehdr.e_phentsize * me->ehdr.e_phnum)) { + fprintf(stderr, "elfu_check: Found section overlapping with PHDRs: %s.\n", + elfu_modelScnName(me, sortedSecs[i])); + } + } + + free(sortedSecs); + + return 0; +} diff --git a/src/model/count.c b/src/model/count.c index d42f806..274b9d8 100644 --- a/src/model/count.c +++ b/src/model/count.c @@ -1,13 +1,17 @@ +#include #include #include +/* NULL section is not counted! */ size_t elfu_countSections(ElfuElf *me) { ElfuScn *ms; size_t i = 0; + assert(me); + CIRCLEQ_FOREACH(ms, &me->scnList, elem) { i++; } @@ -21,6 +25,8 @@ size_t elfu_countPHDRs(ElfuElf *me) ElfuPhdr *mp; size_t i = 0; + assert(me); + CIRCLEQ_FOREACH(mp, &me->phdrList, elem) { i++; } diff --git a/src/model/fromFile.c b/src/model/fromFile.c index f349335..26ce6a7 100644 --- a/src/model/fromFile.c +++ b/src/model/fromFile.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -72,6 +73,13 @@ ElfuScn* elfu_modelFromSection(Elf_Scn *scn) ElfuElf* elfu_modelFromElf(Elf *e) { ElfuElf *me; + Elf_Scn *scn; + size_t shstrndx; + size_t i, n; + + if (elf_getshdrstrndx(e, &shstrndx) != 0) { + shstrndx = 0; + } me = malloc(sizeof(ElfuElf)); if (!me) { @@ -80,6 +88,7 @@ ElfuElf* elfu_modelFromElf(Elf *e) CIRCLEQ_INIT(&me->scnList); CIRCLEQ_INIT(&me->phdrList); + me->shstrtab = NULL; /* * General stuff @@ -98,19 +107,22 @@ ElfuElf* elfu_modelFromElf(Elf *e) /* * Sections */ - Elf_Scn *scn; - scn = elf_getscn(e, 1); + i = 1; while (scn) { ElfuScn *ms = elfu_modelFromSection(scn); if (ms) { CIRCLEQ_INSERT_TAIL(&me->scnList, ms, elem); + if (i == shstrndx) { + me->shstrtab = ms; + } } else { goto out; } scn = elf_nextscn(e, scn); + i++; } @@ -118,8 +130,6 @@ ElfuElf* elfu_modelFromElf(Elf *e) /* * Segments */ - size_t i, n; - if (elf_getphdrnum(e, &n)) { fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1)); } diff --git a/src/model/section-name.c b/src/model/section-name.c new file mode 100644 index 0000000..0e5d903 --- /dev/null +++ b/src/model/section-name.c @@ -0,0 +1,27 @@ +#include +#include + +#include +#include + +#include + + + +char* elfu_modelScnName(ElfuElf *me, ElfuScn *ms) +{ + assert(me); + assert(ms); + + if (!me->shstrtab) { + return NULL; + } + + if (CIRCLEQ_EMPTY(&me->shstrtab->dataList)) { + return NULL; + } + + /* Don't take multiple data parts into account. */ + ElfuData *md = me->shstrtab->dataList.cqh_first; + return &((char*)md->data.d_buf)[ms->shdr.sh_name]; +} -- 2.30.2