summaryrefslogtreecommitdiff
path: root/libelf
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-06-04 16:25:37 +0200
committerMark Wielaard <mjw@redhat.com>2015-06-09 22:50:31 +0200
commitede1d9d8aa4b04810e1ee04fcec9386e63f48d77 (patch)
treea756cc1fed073f06a4c8671486cfa093d44a3132 /libelf
parent9a9f7f6667ae156c8fb8e1290d855d8b8e893461 (diff)
downloadelfutils-ede1d9d8aa4b04810e1ee04fcec9386e63f48d77.tar.gz
libelf: Make sure elf_getdata_rawchunk returns aligned data.
elf_getdata_rawchunk might return an unaligned buffer for the requested ELF data type. Make sure the data is also correctly aligned when using an mmapped file. Also add some missing alignments for ELF data types for __libelf_type_align (the missing types could also make elf_getdata to return unaligned data). Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libelf')
-rw-r--r--libelf/ChangeLog8
-rw-r--r--libelf/elf_getdata.c9
-rw-r--r--libelf/elf_getdata_rawchunk.c20
3 files changed, 34 insertions, 3 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 25f673db..30017cd7 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,11 @@
+2015-06-04 Mark Wielaard <mjw@redhat.com>
+
+ * elf_getdata.c (__libelf_type_aligns): Add entries for ELF_T_EHDR,
+ ELF_T_OFF, ELF_T_PHDR, ELF_T_SHDR, ELF_T_SWORD, ELF_T_XWORD,
+ ELF_T_SXWORD, ELF_T_GNUHASH, ELF_T_AUXV.
+ * elf_getdata_rawchunk.c (elf_getdata_rawchunk): Check alignment
+ of rawdata against requested type.
+
2015-06-02 Mark Wielaard <mjw@redhat.com>
* elf_getdata.c (convert_data): Make sure source data is properly
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
index 1a4981ef..770e0355 100644
--- a/libelf/elf_getdata.c
+++ b/libelf/elf_getdata.c
@@ -83,8 +83,15 @@ const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM]
# define TYPE_ALIGNS(Bits) \
{ \
[ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
+ [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \
[ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
+ [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)), \
+ [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)), \
+ [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)), \
+ [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)), \
[ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \
+ [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)), \
+ [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)), \
[ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \
[ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \
[ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \
@@ -97,6 +104,8 @@ const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM]
[ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
[ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
[ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
+ [ELF_T_GNUHASH] = __alignof__ (Elf32_Word), \
+ [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \
}
[EV_CURRENT - 1] =
{
diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c
index 63a9914f..5cc11e70 100644
--- a/libelf/elf_getdata_rawchunk.c
+++ b/libelf/elf_getdata_rawchunk.c
@@ -79,9 +79,24 @@ elf_getdata_rawchunk (elf, offset, size, type)
rwlock_rdlock (elf->lock);
- /* If the file is mmap'ed we can use it directly. */
+ size_t align = __libelf_type_align (elf->class, type);
if (elf->map_address != NULL)
- rawchunk = elf->map_address + elf->start_offset + offset;
+ {
+ /* If the file is mmap'ed we can use it directly, if aligned for type. */
+ char *rawdata = elf->map_address + elf->start_offset + offset;
+ if (ALLOW_UNALIGNED ||
+ ((uintptr_t) rawdata & (align - 1)) == 0)
+ rawchunk = rawdata;
+ else
+ {
+ /* We allocate the memory and memcpy it to get aligned data. */
+ rawchunk = malloc (size);
+ if (rawchunk == NULL)
+ goto nomem;
+ memcpy (rawchunk, rawdata, size);
+ flags = ELF_F_MALLOCED;
+ }
+ }
else
{
/* We allocate the memory and read the data from the file. */
@@ -108,7 +123,6 @@ elf_getdata_rawchunk (elf, offset, size, type)
}
/* Copy and/or convert the data as needed for aligned native-order access. */
- size_t align = __libelf_type_align (elf->class, type);
void *buffer;
if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
{