diff options
| author | Mark Wielaard <[email protected]> | 2018-11-18 00:21:49 +0100 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2018-11-21 12:30:12 +0100 |
| commit | 5f9fab9efb042d803fcd2546f29613493f55d666 (patch) | |
| tree | a985fc7c4f4dd356ce161b9d5477802254b7c025 /libelf/elf32_updatefile.c | |
| parent | f5810ec76caed5155c27c2ed3d0ba2b3f0d4ad22 (diff) | |
libelf: Get alignment correct when calling conversion functions.
When writing out data that needs to be converted we have to make sure
the conversion function is called on correctly aligned buffers. When
using mmap this might mean we have to convert into a temporarily buffer
if the user wants to write out the section at a location that is not
correctly aligned for the section type.
Older gas would generate misaligned ELF notes for the .version
directive. When copying over such notes using mmap from files with
a different endianness using mmap we would get the alignment of the
conversion destination wrong.
The new testcase would fail with configure --enable-sanitize-undefined
on little endian systems. The GCC undefinited sanitizer caught a similar
issue with testfile1 on big endian systems.
gelf_xlate.h:47:1: runtime error: member access within misaligned address
0x7f8145d770d5 for type 'struct Elf32_Nhdr', which requires 4 byte alignment
Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libelf/elf32_updatefile.c')
| -rw-r--r-- | libelf/elf32_updatefile.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c index f2e9a288..284bacc9 100644 --- a/libelf/elf32_updatefile.c +++ b/libelf/elf32_updatefile.c @@ -1,5 +1,5 @@ /* Write changed data structures. - Copyright (C) 2000-2010, 2014, 2015, 2016 Red Hat, Inc. + Copyright (C) 2000-2010, 2014, 2015, 2016, 2018 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2000. @@ -354,7 +354,9 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) user's section data with the latest one, rather than crashing. */ - if (unlikely (change_bo)) + if (unlikely (change_bo + && dl->data.d.d_size != 0 + && dl->data.d.d_type != ELF_T_BYTE)) { #if EV_NUM != 2 xfct_t fctp; @@ -364,9 +366,33 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) # define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type] #endif - /* Do the real work. */ - (*fctp) (last_position, dl->data.d.d_buf, - dl->data.d.d_size, 1); + size_t align; + align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS), + dl->data.d.d_type); + if ((((uintptr_t) last_position) + & (uintptr_t) (align - 1)) == 0) + { + /* No need to copy, we can convert directly. */ + (*fctp) (last_position, dl->data.d.d_buf, + dl->data.d.d_size, 1); + } + else + { + /* We have to do the conversion on properly + aligned memory first. */ + size_t size = dl->data.d.d_size; + char *converted = aligned_alloc (align, size); + if (converted == NULL) + { + __libelf_seterrno (ELF_E_NOMEM); + return 1; + } + (*fctp) (converted, dl->data.d.d_buf, size, 1); + + /* And then write it to the mmapped file. */ + memcpy (last_position, converted, size); + free (converted); + } last_position += dl->data.d.d_size; } |
