summaryrefslogtreecommitdiffstats
path: root/libelf
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-05-14 12:34:26 +0200
committerMark Wielaard <mjw@redhat.com>2015-05-27 17:10:48 +0200
commit77482c4bf63a92166191e0b8531e9781f6fddbf3 (patch)
treeac8b53653eddd09edc3314fd2af48d55f92af224 /libelf
parent2b250b759799eaa43bce1643b7072be8c5c19c01 (diff)
downloadandroid_external_elfutils-77482c4bf63a92166191e0b8531e9781f6fddbf3.tar.gz
android_external_elfutils-77482c4bf63a92166191e0b8531e9781f6fddbf3.tar.bz2
android_external_elfutils-77482c4bf63a92166191e0b8531e9781f6fddbf3.zip
libelf: Use posix_fallocate instead of ftruncate to extend ELF file.
This fixes an obscure SIGBUS error when using ELF_C_WRITE_MMAP on an ELF file that needs extending when the underlying file system is (nearly) full. Use posix_fallocate to make sure the file content is really there. Using ftruncate might mean the file is extended, but space isn't allocated yet. This might cause a SIGBUS once we write into the mmapped space and the disk is full. Using fallocate might fail on some file systems. posix_fallocate is required to extend the file and allocate enough space even if the underlying filesystem would normally return EOPNOTSUPP or the kernel doesn't implement the fallocate syscall. Also posix_fallocate has been in glibc since 2.1.94, while support for fallocate was only added in 2.10 and kernel 2.6.23. Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libelf')
-rw-r--r--libelf/ChangeLog5
-rw-r--r--libelf/elf_update.c16
2 files changed, 18 insertions, 3 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 2d10b83e..ed2ddd88 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-14 Mark Wielaard <mjw@redhat.com>
+
+ * elf_update.c (write_file): Use posix_fallocate instead of
+ ftruncate to extend file if necessary.
+
2015-05-13 Mark Wielaard <mjw@redhat.com>
* elf32_updatenull.c (default_ehdr): If e_phnum is zero then set
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
index 54c20f50..9e34c466 100644
--- a/libelf/elf_update.c
+++ b/libelf/elf_update.c
@@ -1,5 +1,5 @@
/* Update data structures for changes and write them out.
- Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2015 Red Hat, Inc.
This file is part of elfutils.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -32,6 +32,7 @@
#endif
#include <libelf.h>
+#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -56,11 +57,19 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
We cannot do this if this file is in an archive. We also don't
do it *now* if we are shortening the file since this would
prevent programs to use the data of the file in generating the
- new file. We truncate the file later in this case. */
+ new file. We truncate the file later in this case.
+
+ Note we use posix_fallocate to make sure the file content is really
+ there. Using ftruncate might mean the file is extended, but space
+ isn't allocated yet. This might cause a SIGBUS once we write into
+ the mmapped space and the disk is full. Using fallocate might fail
+ on some file systems. posix_fallocate is required to extend the file
+ and allocate enough space even if the underlying filesystem would
+ normally return EOPNOTSUPP. */
if (elf->parent == NULL
&& (elf->maximum_size == ~((size_t) 0)
|| (size_t) size > elf->maximum_size)
- && unlikely (ftruncate (elf->fildes, size) != 0))
+ && unlikely (posix_fallocate (elf->fildes, 0, size) != 0))
{
__libelf_seterrno (ELF_E_WRITE_ERROR);
return -1;
@@ -94,6 +103,7 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
size = -1;
}
+ /* Reduce the file size if necessary. */
if (size != -1
&& elf->parent == NULL
&& elf->maximum_size != ~((size_t) 0)