From 493e2676626b530a45fcc17040915f34fa0c5dd3 Mon Sep 17 00:00:00 2001 From: Vincent Mihalkovic Date: Mon, 6 Feb 2023 14:39:29 +0100 Subject: [PATCH] add parsing for dynamic sections 9109a696f3289ba00eaa222fd432755ec4287e28 --- src/readelf.c | 295 +++++++++++++++++++++++++++++++------------------- src/readelf.h | 103 ++++++++++++++++++ 2 files changed, 289 insertions(+), 109 deletions(-) diff --git a/src/readelf.c b/src/readelf.c index c101483..cdc211f 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -62,13 +62,12 @@ private uint64_t getu64(int, uint64_t); #define MAX_PHNUM 128 #define MAX_SHNUM 32768 -#define SIZE_UNKNOWN ((off_t)-1) +#define SIZE_UNKNOWN CAST(off_t, -1) private int toomany(struct magic_set *ms, const char *name, uint16_t num) { - if (file_printf(ms, ", too many %s (%u)", name, num - ) == -1) + if (file_printf(ms, ", too many %s (%u)", name, num) == -1) return -1; return 0; } @@ -143,54 +142,55 @@ getu64(int swap, uint64_t value) #define elf_getu64(swap, value) getu64(swap, value) #define xsh_addr (clazz == ELFCLASS32 \ - ? (void *)&sh32 \ - : (void *)&sh64) + ? CAST(void *, &sh32) \ + : CAST(void *, &sh64)) #define xsh_sizeof (clazz == ELFCLASS32 \ ? sizeof(sh32) \ : sizeof(sh64)) -#define xsh_size (size_t)(clazz == ELFCLASS32 \ +#define xsh_size CAST(size_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_size) \ - : elf_getu64(swap, sh64.sh_size)) -#define xsh_offset (off_t)(clazz == ELFCLASS32 \ + : elf_getu64(swap, sh64.sh_size))) +#define xsh_offset CAST(off_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_offset) \ - : elf_getu64(swap, sh64.sh_offset)) + : elf_getu64(swap, sh64.sh_offset))) #define xsh_type (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_type) \ : elf_getu32(swap, sh64.sh_type)) #define xsh_name (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_name) \ : elf_getu32(swap, sh64.sh_name)) + #define xph_addr (clazz == ELFCLASS32 \ - ? (void *) &ph32 \ - : (void *) &ph64) + ? CAST(void *, &ph32) \ + : CAST(void *, &ph64)) #define xph_sizeof (clazz == ELFCLASS32 \ ? sizeof(ph32) \ : sizeof(ph64)) #define xph_type (clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_type) \ : elf_getu32(swap, ph64.p_type)) -#define xph_offset (off_t)(clazz == ELFCLASS32 \ +#define xph_offset CAST(off_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_offset) \ - : elf_getu64(swap, ph64.p_offset)) -#define xph_align (size_t)((clazz == ELFCLASS32 \ - ? (off_t) (ph32.p_align ? \ - elf_getu32(swap, ph32.p_align) : 4) \ - : (off_t) (ph64.p_align ? \ - elf_getu64(swap, ph64.p_align) : 4))) -#define xph_vaddr (size_t)((clazz == ELFCLASS32 \ - ? (off_t) (ph32.p_vaddr ? \ - elf_getu32(swap, ph32.p_vaddr) : 4) \ - : (off_t) (ph64.p_vaddr ? \ - elf_getu64(swap, ph64.p_vaddr) : 4))) -#define xph_filesz (size_t)((clazz == ELFCLASS32 \ + : elf_getu64(swap, ph64.p_offset))) +#define xph_align CAST(size_t, (clazz == ELFCLASS32 \ + ? CAST(off_t, (ph32.p_align ? \ + elf_getu32(swap, ph32.p_align) : 4))\ + : CAST(off_t, (ph64.p_align ? \ + elf_getu64(swap, ph64.p_align) : 4)))) +#define xph_vaddr CAST(size_t, (clazz == ELFCLASS32 \ + ? CAST(off_t, (ph32.p_vaddr ? \ + elf_getu32(swap, ph32.p_vaddr) : 4))\ + : CAST(off_t, (ph64.p_vaddr ? \ + elf_getu64(swap, ph64.p_vaddr) : 4)))) +#define xph_filesz CAST(size_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_filesz) \ : elf_getu64(swap, ph64.p_filesz))) -#define xnh_addr (clazz == ELFCLASS32 \ - ? (void *)&nh32 \ - : (void *)&nh64) -#define xph_memsz (size_t)((clazz == ELFCLASS32 \ +#define xph_memsz CAST(size_t, ((clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_memsz) \ - : elf_getu64(swap, ph64.p_memsz))) + : elf_getu64(swap, ph64.p_memsz)))) +#define xnh_addr (clazz == ELFCLASS32 \ + ? CAST(void *, &nh32) \ + : CAST(void *, &nh64)) #define xnh_sizeof (clazz == ELFCLASS32 \ ? sizeof(nh32) \ : sizeof(nh64)) @@ -203,24 +203,36 @@ getu64(int swap, uint64_t value) #define xnh_descsz (clazz == ELFCLASS32 \ ? elf_getu32(swap, nh32.n_descsz) \ : elf_getu32(swap, nh64.n_descsz)) -#define prpsoffsets(i) (clazz == ELFCLASS32 \ - ? prpsoffsets32[i] \ - : prpsoffsets64[i]) + +#define xdh_addr (clazz == ELFCLASS32 \ + ? CAST(void *, &dh32) \ + : CAST(void *, &dh64)) +#define xdh_sizeof (clazz == ELFCLASS32 \ + ? sizeof(dh32) \ + : sizeof(dh64)) +#define xdh_tag (clazz == ELFCLASS32 \ + ? elf_getu32(swap, dh32.d_tag) \ + : elf_getu64(swap, dh64.d_tag)) +#define xdh_val (clazz == ELFCLASS32 \ + ? elf_getu32(swap, dh32.d_un.d_val) \ + : elf_getu64(swap, dh64.d_un.d_val)) + #define xcap_addr (clazz == ELFCLASS32 \ - ? (void *)&cap32 \ - : (void *)&cap64) + ? CAST(void *, &cap32) \ + : CAST(void *, &cap64)) #define xcap_sizeof (clazz == ELFCLASS32 \ - ? sizeof cap32 \ - : sizeof cap64) + ? sizeof(cap32) \ + : sizeof(cap64)) #define xcap_tag (clazz == ELFCLASS32 \ ? elf_getu32(swap, cap32.c_tag) \ : elf_getu64(swap, cap64.c_tag)) #define xcap_val (clazz == ELFCLASS32 \ ? elf_getu32(swap, cap32.c_un.c_val) \ : elf_getu64(swap, cap64.c_un.c_val)) + #define xauxv_addr (clazz == ELFCLASS32 \ - ? (void *)&auxv32 \ - : (void *)&auxv64) + ? CAST(void *, &auxv32) \ + : CAST(void *, &auxv64)) #define xauxv_sizeof (clazz == ELFCLASS32 \ ? sizeof(auxv32) \ : sizeof(auxv64)) @@ -231,6 +243,10 @@ getu64(int swap, uint64_t value) ? elf_getu32(swap, auxv32.a_v) \ : elf_getu64(swap, auxv64.a_v)) +#define prpsoffsets(i) (clazz == ELFCLASS32 \ + ? prpsoffsets32[i] \ + : prpsoffsets64[i]) + #ifdef ELFCORE /* * Try larger offsets first to avoid false matches @@ -269,8 +285,8 @@ static const size_t prpsoffsets64[] = { 16, /* FreeBSD, 64-bit */ }; -#define NOFFSETS32 (sizeof prpsoffsets32 / sizeof prpsoffsets32[0]) -#define NOFFSETS64 (sizeof prpsoffsets64 / sizeof prpsoffsets64[0]) +#define NOFFSETS32 (sizeof(prpsoffsets32) / sizeof(prpsoffsets32[0])) +#define NOFFSETS64 (sizeof(prpsoffsets64) / sizeof(prpsoffsets64[0])) #define NOFFSETS (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64) @@ -349,7 +365,8 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, * Loop through all the program headers. */ for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + if (pread(fd, xph_addr, xph_sizeof, off) < + CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; } @@ -392,7 +409,7 @@ static void do_note_netbsd_version(struct magic_set *ms, int swap, void *v) { uint32_t desc; - (void)memcpy(&desc, v, sizeof(desc)); + memcpy(&desc, v, sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, ", for NetBSD") == -1) @@ -438,7 +455,7 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v) { uint32_t desc; - (void)memcpy(&desc, v, sizeof(desc)); + memcpy(&desc, v, sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, ", for FreeBSD") == -1) return; @@ -536,7 +553,7 @@ do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, } if (file_printf(ms, ", BuildID[%s]=", btype) == -1) return 1; - (void)memcpy(desc, &nbuf[doff], descsz); + memcpy(desc, &nbuf[doff], descsz); for (i = 0; i < descsz; i++) if (file_printf(ms, "%02x", desc[i]) == -1) return 1; @@ -560,7 +577,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && type == NT_GNU_VERSION && descsz == 16) { uint32_t desc[4]; - (void)memcpy(desc, &nbuf[doff], sizeof(desc)); + memcpy(desc, &nbuf[doff], sizeof(desc)); *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for GNU/") == -1) @@ -627,7 +644,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for DragonFly") == -1) return 1; - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); + memcpy(&desc, &nbuf[doff], sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, " %d.%d.%d", desc / 100000, desc / 10000 % 10, desc % 10000) == -1) @@ -657,7 +674,7 @@ do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, int did = 0; *flags |= FLAGS_DID_NETBSD_PAX; - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); + memcpy(&desc, &nbuf[doff], sizeof(desc)); desc = elf_getu32(swap, desc); if (desc && file_printf(ms, ", PaX: ") == -1) @@ -957,7 +974,7 @@ do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, nval = 0; for (size_t off = 0; off + elsize <= descsz; off += elsize) { - (void)memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof); + memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof); /* Limit processing to 50 vector entries to prevent DoS */ if (nval++ >= 50) { file_error(ms, 0, "Too many ELF Auxv elements"); @@ -1021,6 +1038,38 @@ do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, #endif } +private size_t +dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size, + int clazz, int swap) +{ + Elf32_Dyn dh32; + Elf64_Dyn dh64; + unsigned char *dbuf = CAST(unsigned char *, vbuf); + + if (xdh_sizeof + offset > size) { + /* + * We're out of note headers. + */ + return xdh_sizeof + offset; + } + + memcpy(xdh_addr, &dbuf[offset], xdh_sizeof); + offset += xdh_sizeof; + + switch (xdh_tag) { + case DT_FLAGS_1: + if (xdh_val == DF_1_PIE) + ms->mode |= 0111; + else + ms->mode &= ~0111; + break; + default: + break; + } + return offset; +} + + private size_t donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, int clazz, int swap, size_t align, int *flags, uint16_t *notecount, @@ -1043,7 +1092,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, return xnh_sizeof + offset; } - (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); + memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); offset += xnh_sizeof; namesz = xnh_namesz; @@ -1057,14 +1106,14 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, } if (namesz & 0x80000000) { - (void)file_printf(ms, ", bad note name size %#lx", - (unsigned long)namesz); + file_printf(ms, ", bad note name size %#lx", + CAST(unsigned long, namesz)); return 0; } if (descsz & 0x80000000) { - (void)file_printf(ms, ", bad note description size %#lx", - (unsigned long)descsz); + file_printf(ms, ", bad note description size %#lx", + CAST(unsigned long, descsz)); return 0; } @@ -1118,35 +1167,25 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, return offset; } - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + if (namesz == 7 && strcmp(CAST(char *, &nbuf[noff]), "NetBSD") == 0) { + int descw, flag; + const char *str, *tag; if (descsz > 100) descsz = 100; switch (xnh_type) { case NT_NETBSD_VERSION: return offset; case NT_NETBSD_MARCH: - if (*flags & FLAGS_DID_NETBSD_MARCH) - return offset; - *flags |= FLAGS_DID_NETBSD_MARCH; - if (file_printf(ms, ", compiled for: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return offset; + flag = FLAGS_DID_NETBSD_MARCH; + tag = "compiled for"; break; case NT_NETBSD_CMODEL: - if (*flags & FLAGS_DID_NETBSD_CMODEL) - return offset; - *flags |= FLAGS_DID_NETBSD_CMODEL; - if (file_printf(ms, ", compiler model: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return offset; + flag = FLAGS_DID_NETBSD_CMODEL; + tag = "compiler model"; break; case NT_NETBSD_EMULATION: - if (*flags & FLAGS_DID_NETBSD_EMULATION) - return offset; - *flags |= FLAGS_DID_NETBSD_EMULATION; - if (file_printf(ms, ", emulation: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return offset; + flag = FLAGS_DID_NETBSD_EMULATION; + tag = "emulation:"; break; default: if (*flags & FLAGS_DID_NETBSD_UNKNOWN) @@ -1154,8 +1193,15 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, *flags |= FLAGS_DID_NETBSD_UNKNOWN; if (file_printf(ms, ", note=%u", xnh_type) == -1) return offset; - break; + return offset; } + + if (*flags & flag) + return offset; + str = CAST(const char *, &nbuf[doff]); + descw = CAST(int, descsz); + *flags |= flag; + file_printf(ms, ", %s: %.*s", tag, descw, str); return offset; } @@ -1236,7 +1282,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, /* Read offset of name section to be able to read section names later */ if (pread(fd, xsh_addr, xsh_sizeof, CAST(off_t, (off + size * strtab))) - < (ssize_t)xsh_sizeof) { + < CAST(ssize_t, xsh_sizeof)) { if (file_printf(ms, ", missing section headers") == -1) return -1; return 0; @@ -1245,7 +1291,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, for ( ; num; num--) { /* Read the name of this section. */ - if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) { + if ((namesize = pread(fd, name, sizeof(name) - 1, + name_off + xsh_name)) == -1) { file_badread(ms); return -1; } @@ -1255,7 +1302,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, stripped = 0; } - if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) { + if (pread(fd, xsh_addr, xsh_sizeof, off) < + CAST(ssize_t, xsh_sizeof)) { file_badread(ms); return -1; } @@ -1281,14 +1329,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, /* Things we can determine when we seek */ switch (xsh_type) { case SHT_NOTE: - if ((uintmax_t)(xsh_size + xsh_offset) > - (uintmax_t)fsize) { + if (CAST(uintmax_t, (xsh_size + xsh_offset)) > + CAST(uintmax_t, fsize)) { if (file_printf(ms, ", note offset/size %#" INTMAX_T_FORMAT "x+%#" INTMAX_T_FORMAT "x exceeds" " file size %#" INTMAX_T_FORMAT "x", - (uintmax_t)xsh_offset, (uintmax_t)xsh_size, - (uintmax_t)fsize) == -1) + CAST(uintmax_t, xsh_offset), + CAST(uintmax_t, xsh_size), + CAST(uintmax_t, fsize)) == -1) return -1; return 0; } @@ -1298,7 +1347,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, return -1; } if (pread(fd, nbuf, xsh_size, xsh_offset) < - (ssize_t)xsh_size) { + CAST(ssize_t, xsh_size)) { file_badread(ms); free(nbuf); return -1; @@ -1306,9 +1355,9 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, noff = 0; for (;;) { - if (noff >= (off_t)xsh_size) + if (noff >= CAST(off_t, xsh_size)) break; - noff = donote(ms, nbuf, (size_t)noff, + noff = donote(ms, nbuf, CAST(size_t, noff), xsh_size, clazz, swap, 4, flags, notecount, fd, 0, 0, 0); if (noff == 0) @@ -1330,7 +1379,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (nbadcap > 5) break; - if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) { + if (lseek(fd, xsh_offset, SEEK_SET) + == CAST(off_t, -1)) { file_badseek(ms); return -1; } @@ -1339,11 +1389,12 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, Elf32_Cap cap32; Elf64_Cap cap64; char cbuf[/*CONSTCOND*/ - MAX(sizeof cap32, sizeof cap64)]; - if ((coff += xcap_sizeof) > (off_t)xsh_size) + MAX(sizeof(cap32), sizeof(cap64))]; + if ((coff += xcap_sizeof) > + CAST(off_t, xsh_size)) break; - if (read(fd, cbuf, (size_t)xcap_sizeof) != - (ssize_t)xcap_sizeof) { + if (read(fd, cbuf, CAST(size_t, xcap_sizeof)) != + CAST(ssize_t, xcap_sizeof)) { file_badread(ms); return -1; } @@ -1377,7 +1428,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, #endif break; } - (void)memcpy(xcap_addr, cbuf, xcap_sizeof); + memcpy(xcap_addr, cbuf, xcap_sizeof); switch (xcap_tag) { case CA_SUNW_NULL: break; @@ -1392,8 +1443,9 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, ", with unknown capability " "%#" INT64_T_FORMAT "x = %#" INT64_T_FORMAT "x", - (unsigned long long)xcap_tag, - (unsigned long long)xcap_val) == -1) + CAST(unsigned long long, xcap_tag), + CAST(unsigned long long, xcap_val)) + == -1) return -1; if (nbadcap++ > 2) coff = xsh_size; @@ -1446,12 +1498,12 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (file_printf(ms, " unknown hardware capability %#" INT64_T_FORMAT "x", - (unsigned long long)cap_hw1) == -1) + CAST(unsigned long long, cap_hw1)) == -1) return -1; } else { if (file_printf(ms, " hardware capability %#" INT64_T_FORMAT "x", - (unsigned long long)cap_hw1) == -1) + CAST(unsigned long long, cap_hw1)) == -1) return -1; } } @@ -1468,7 +1520,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (file_printf(ms, ", with unknown software capability %#" INT64_T_FORMAT "x", - (unsigned long long)cap_sf1) == -1) + CAST(unsigned long long, cap_sf1)) == -1) return -1; } return 0; @@ -1487,9 +1539,9 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, Elf32_Phdr ph32; Elf64_Phdr ph64; const char *linking_style = "statically"; - const char *interp = ""; unsigned char nbuf[BUFSIZ]; char ibuf[BUFSIZ]; + char interp[BUFSIZ]; ssize_t bufsize; size_t offset, align, len; @@ -1499,8 +1551,11 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, return 0; } + interp[0] = '\0'; for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + int doread; + if (pread(fd, xph_addr, xph_sizeof, off) < + CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; } @@ -1513,6 +1568,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, switch (xph_type) { case PT_DYNAMIC: linking_style = "dynamically"; + doread = 1; break; case PT_NOTE: if (sh_num) /* Did this through section headers */ @@ -1521,21 +1577,16 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, align < 4) { if (file_printf(ms, ", invalid note alignment %#lx", - (unsigned long)align) == -1) + CAST(unsigned long, align)) == -1) return -1; align = 4; } /*FALLTHROUGH*/ case PT_INTERP: - len = xph_filesz < sizeof(nbuf) ? xph_filesz - : sizeof(nbuf); - bufsize = pread(fd, nbuf, len, xph_offset); - if (bufsize == -1) { - file_badread(ms); - return -1; - } + doread = 1; break; default: + doread = 0; if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { /* Maybe warn here? */ continue; @@ -1543,14 +1594,39 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, break; } + if (doread) { + len = xph_filesz < sizeof(nbuf) ? xph_filesz + : sizeof(nbuf); + bufsize = pread(fd, nbuf, len, xph_offset); + if (bufsize == -1) { + file_badread(ms); + return -1; + } + } else + len = 0; + /* Things we can determine when we seek */ switch (xph_type) { + case PT_DYNAMIC: + offset = 0; + for (;;) { + if (offset >= (size_t)bufsize) + break; + offset = dodynamic(ms, nbuf, offset, + CAST(size_t, bufsize), clazz, swap); + if (offset == 0) + break; + } + if (ms->flags & MAGIC_MIME) + continue; + break; + case PT_INTERP: if (bufsize && nbuf[0]) { nbuf[bufsize - 1] = '\0'; - interp = (const char *)nbuf; + memcpy(interp, nbuf, bufsize); } else - interp = "*empty*"; + strlcpy(interp, "*empty*", sizeof(interp)); break; case PT_NOTE: /* @@ -1562,7 +1638,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, if (offset >= (size_t)bufsize) break; offset = donote(ms, nbuf, offset, - (size_t)bufsize, clazz, swap, align, + CAST(size_t, bufsize), clazz, swap, align, flags, notecount, fd, 0, 0, 0); if (offset == 0) break; @@ -1591,7 +1667,7 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) size_t nbytes = b->flen; union { int32_t l; - char c[sizeof (int32_t)]; + char c[sizeof(int32_t)]; } u; int clazz; int swap; @@ -1619,7 +1695,8 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) /* * If we cannot seek, it must be a pipe, socket or fifo. */ - if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE)) + if((lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) + && (errno == ESPIPE)) fd = file_pipe2file(ms, fd, buf, nbytes); if (fstat(fd, &st) == -1) { diff --git a/src/readelf.h b/src/readelf.h index ef880b9..f2f3dc3 100644 --- a/src/readelf.h +++ b/src/readelf.h @@ -430,4 +430,107 @@ typedef struct { #define AV_386_SSE4_1 0x00800000 #define AV_386_SSE4_2 0x01000000 +/* + * Dynamic Section structure array + */ +typedef struct { + Elf32_Word d_tag; /* entry tag value */ + union { + Elf32_Addr d_ptr; + Elf32_Word d_val; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Xword d_tag; /* entry tag value */ + union { + Elf64_Addr d_ptr; + Elf64_Xword d_val; + } d_un; +} Elf64_Dyn; + +/* d_tag */ +#define DT_NULL 0 /* Marks end of dynamic array */ +#define DT_NEEDED 1 /* Name of needed library (DT_STRTAB offset) */ +#define DT_PLTRELSZ 2 /* Size, in bytes, of relocations in PLT */ +#define DT_PLTGOT 3 /* Address of PLT and/or GOT */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocation table */ +#define DT_RELASZ 8 /* Size, in bytes, of DT_RELA table */ +#define DT_RELAENT 9 /* Size, in bytes, of one DT_RELA entry */ +#define DT_STRSZ 10 /* Size, in bytes, of DT_STRTAB table */ +#define DT_SYMENT 11 /* Size, in bytes, of one DT_SYMTAB entry */ +#define DT_INIT 12 /* Address of initialization function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Shared object name (DT_STRTAB offset) */ +#define DT_RPATH 15 /* Library search path (DT_STRTAB offset) */ +#define DT_SYMBOLIC 16 /* Start symbol search within local object */ +#define DT_REL 17 /* Address of Rel relocation table */ +#define DT_RELSZ 18 /* Size, in bytes, of DT_REL table */ +#define DT_RELENT 19 /* Size, in bytes, of one DT_REL entry */ +#define DT_PLTREL 20 /* Type of PLT relocation entries */ +#define DT_DEBUG 21 /* Used for debugging; unspecified */ +#define DT_TEXTREL 22 /* Relocations might modify non-writable seg */ +#define DT_JMPREL 23 /* Address of relocations associated with PLT */ +#define DT_BIND_NOW 24 /* Process all relocations at load-time */ +#define DT_INIT_ARRAY 25 /* Address of initialization function array */ +#define DT_FINI_ARRAY 26 /* Size, in bytes, of DT_INIT_ARRAY array */ +#define DT_INIT_ARRAYSZ 27 /* Address of termination function array */ +#define DT_FINI_ARRAYSZ 28 /* Size, in bytes, of DT_FINI_ARRAY array*/ +#define DT_RUNPATH 29 /* overrides DT_RPATH */ +#define DT_FLAGS 30 /* Encodes ORIGIN, SYMBOLIC, TEXTREL, BIND_NOW, STATIC_TLS */ +#define DT_ENCODING 31 /* ??? */ +#define DT_PREINIT_ARRAY 32 /* Address of pre-init function array */ +#define DT_PREINIT_ARRAYSZ 33 /* Size, in bytes, of DT_PREINIT_ARRAY array */ +#define DT_NUM 34 + +#define DT_LOOS 0x60000000 /* Operating system specific range */ +#define DT_VERSYM 0x6ffffff0 /* Symbol versions */ +#define DT_FLAGS_1 0x6ffffffb /* ELF dynamic flags */ +#define DT_VERDEF 0x6ffffffc /* Versions defined by file */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of versions defined by file */ +#define DT_VERNEED 0x6ffffffe /* Versions needed by file */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of versions needed by file */ +#define DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 /* Processor-specific range */ +#define DT_HIPROC 0x7fffffff + +/* Flag values for DT_FLAGS */ +#define DF_ORIGIN 0x00000001 /* uses $ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* */ +#define DF_TEXTREL 0x00000004 /* */ +#define DF_BIND_NOW 0x00000008 /* */ +#define DF_STATIC_TLS 0x00000010 /* */ + +/* Flag values for DT_FLAGS_1 */ +#define DF_1_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Unused */ +#define DF_1_GROUP 0x00000004 /* Is member of group */ +#define DF_1_NODELETE 0x00000008 /* Cannot be deleted from process */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filters */ +#define DF_1_INITFIRST 0x00000020 /* init/fini takes priority */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Require $ORIGIN processing */ +#define DF_1_DIRECT 0x00000100 /* Enable direct bindings */ +#define DF_1_INTERPOSE 0x00000400 /* Is an interposer */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default library search path */ +#define DF_1_NODUMP 0x00001000 /* Cannot be dumped with dldump(3C) */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative */ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee ends filter's search */ +#define DF_1_DISPRELDNE 0x00008000 /* Did displacement relocation */ +#define DF_1_DISPRELPND 0x00010000 /* Pending displacement relocation */ +#define DF_1_NODIRECT 0x00020000 /* Has non-direct bindings */ +#define DF_1_IGNMULDEF 0x00040000 /* Used internally */ +#define DF_1_NOKSYMS 0x00080000 /* Used internally */ +#define DF_1_NOHDR 0x00100000 /* Used internally */ +#define DF_1_EDITED 0x00200000 /* Has been modified since build */ +#define DF_1_NORELOC 0x00400000 /* Used internally */ +#define DF_1_SYMINTPOSE 0x00800000 /* Has individual symbol interposers */ +#define DF_1_GLOBAUDIT 0x01000000 /* Require global auditing */ +#define DF_1_SINGLETON 0x02000000 /* Has singleton symbols */ +#define DF_1_STUB 0x04000000 /* Stub */ +#define DF_1_PIE 0x08000000 /* Position Independent Executable */ + #endif -- 2.39.1