summaryrefslogtreecommitdiffstats
path: root/libelf/elf_update.c
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2018-08-12 15:35:18 +0200
committerMark Wielaard <[email protected]>2018-09-13 14:25:22 +0200
commitfb0457f4671e7e0f8331453348005ed6beab275e (patch)
tree5efa18a7afd9543e644e4e2ab2b14a4d9f887498 /libelf/elf_update.c
parenta1e892e920bbde60a9daa1f98c105c227ee7427d (diff)
libelf: Fix some issues with ELF_C_RDWR_MMAP.
When ELF_C_RDWR_MMAP is used libelf might have to write overlapping memory when moving the section data or headers. Make sure to use memmove, not memcpy. Also the size of the underlying file might have to change. That means we will have to also extend the mmap region with mremap. Since we are using direct pointers into the mmapped area we cannot move the mmap, only extend it. This might still fail if there is not enough free memory available to extend the mmap region. Two new test programs have been added. elfcopy which copies a whole elf file (using either ELF_C_WRITE or ELF_C_WRITE_MMAP). And addsections which adds new sections to an existing ELF file (using either ELF_C_RDWR or ELF_C_RDWR_MMAP). The newly added test will fail under valgrind without the fixes. Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libelf/elf_update.c')
-rw-r--r--libelf/elf_update.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
index 8ce07829..36997c2b 100644
--- a/libelf/elf_update.c
+++ b/libelf/elf_update.c
@@ -93,13 +93,29 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
ENOSPC. Otherwise we ignore the error and treat it as just hint. */
if (elf->parent == NULL
&& (elf->maximum_size == ~((size_t) 0)
- || (size_t) size > elf->maximum_size)
- && unlikely (posix_fallocate (elf->fildes, 0, size) != 0))
- if (errno == ENOSPC)
- {
- __libelf_seterrno (ELF_E_WRITE_ERROR);
- return -1;
- }
+ || (size_t) size > elf->maximum_size))
+ {
+ if (unlikely (posix_fallocate (elf->fildes, 0, size) != 0))
+ if (errno == ENOSPC)
+ {
+ __libelf_seterrno (ELF_E_WRITE_ERROR);
+ return -1;
+ }
+
+ /* Extend the mmap address if needed. */
+ if (elf->cmd == ELF_C_RDWR_MMAP
+ && (size_t) size > elf->maximum_size)
+ {
+ if (mremap (elf->map_address, elf->maximum_size,
+ size, 0) == MAP_FAILED)
+ {
+ __libelf_seterrno (ELF_E_WRITE_ERROR);
+ return -1;
+ }
+ elf->maximum_size = size;
+ }
+
+ }
/* The file is mmaped. */
if ((class == ELFCLASS32