summaryrefslogtreecommitdiffstats
path: root/libelf/elf32_updatefile.c
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2018-11-18 00:21:49 +0100
committerMark Wielaard <[email protected]>2018-11-21 12:30:12 +0100
commit5f9fab9efb042d803fcd2546f29613493f55d666 (patch)
treea985fc7c4f4dd356ce161b9d5477802254b7c025 /libelf/elf32_updatefile.c
parentf5810ec76caed5155c27c2ed3d0ba2b3f0d4ad22 (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.c36
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;
}