summaryrefslogtreecommitdiffstats
path: root/libelf
diff options
context:
space:
mode:
Diffstat (limited to 'libelf')
-rw-r--r--libelf/ChangeLog5
-rw-r--r--libelf/elf_update.c36
2 files changed, 28 insertions, 13 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index b1d1ecdf..af2438b4 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-05 Mark Wielaard <mjw@redhat.com>
+
+ * elf_update.c (write_file): Only use posix_fallocate when using
+ mmap. Only report failure when errno is ENOSPC.
+
2015-10-09 Josh Stone <jistone@redhat.com>
* libelfP.h (struct Elf): Replace off64_t with off_t.
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
index 00f7a010..c635eb32 100644
--- a/libelf/elf_update.c
+++ b/libelf/elf_update.c
@@ -57,22 +57,11 @@ 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.
-
- Note we use posix_fallocate to make sure the file content is really
- there. Only 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. Note that we do also need to ftruncate
- in case the maximum_size isn't known and the file needs to be shorter
- because posix_fallocate can only extend. */
+ new file. We truncate the file later in this case. */
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))
+ && unlikely (ftruncate (elf->fildes, size) != 0))
{
__libelf_seterrno (ELF_E_WRITE_ERROR);
return -1;
@@ -89,6 +78,27 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
if (elf->map_address != NULL)
{
+ /* When using mmap we want to make sure the file content is
+ really there. Only 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. In glibc posix_fallocate is required to extend the
+ file and allocate enough space even if the underlying
+ filesystem would normally return EOPNOTSUPP. But other
+ implementations might not work as expected. And the glibc
+ fallback case might fail (with unexpected errnos) in some cases.
+ So we only report an error when the call fails and errno is
+ 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;
+ }
+
/* The file is mmaped. */
if ((class == ELFCLASS32
? __elf32_updatemmap (elf, change_bo, shnum)