Mark Wielaard eb0b633
From e4e846b67df12045ee6554bfb568a89b4ed80a71 Mon Sep 17 00:00:00 2001
Mark Wielaard eb0b633
From: Mark Wielaard <mjw@redhat.com>
Mark Wielaard eb0b633
Date: Tue, 16 Jun 2015 14:05:35 +0200
Mark Wielaard eb0b633
Subject: [PATCH] libelf: Always call ftruncate before posix_fallocate to set
Mark Wielaard eb0b633
 the right size.
Mark Wielaard eb0b633
Mark Wielaard eb0b633
When elf_update.c (write_file) doesn't know the current maximum file length
Mark Wielaard eb0b633
it might have to reduce the file size. posix_fallocate can only extend the
Mark Wielaard eb0b633
file. So always call ftruncate before that to set the file size and making
Mark Wielaard eb0b633
sure the backing store is fully there. Add test cases for checking strip
Mark Wielaard eb0b633
in place (eu-strip without -o) actually reduces the file size. But only
Mark Wielaard eb0b633
for non-ET_REL files. We might not be able to strip ET_REL files (except
Mark Wielaard eb0b633
when they are kernel modules) because they might contain "dangling" symbol
Mark Wielaard eb0b633
table entries.
Mark Wielaard eb0b633
Mark Wielaard eb0b633
https://bugzilla.redhat.com/show_bug.cgi?id=1232206
Mark Wielaard eb0b633
Mark Wielaard eb0b633
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Mark Wielaard eb0b633
---
Mark Wielaard eb0b633
 libelf/ChangeLog        |  5 +++++
Mark Wielaard eb0b633
 libelf/elf_update.c     |  7 +++++--
Mark Wielaard eb0b633
 tests/ChangeLog         |  5 +++++
Mark Wielaard eb0b633
 tests/run-strip-test.sh | 13 +++++++++++++
Mark Wielaard eb0b633
 4 files changed, 28 insertions(+), 2 deletions(-)
Mark Wielaard eb0b633
Mark Wielaard eb0b633
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
Mark Wielaard eb0b633
index 30017cd..2d24007 100644
Mark Wielaard eb0b633
--- a/libelf/ChangeLog
Mark Wielaard eb0b633
+++ b/libelf/ChangeLog
Mark Wielaard eb0b633
@@ -1,3 +1,8 @@
Mark Wielaard eb0b633
+2015-06-16  Mark Wielaard  <mjw@redhat.com>
Mark Wielaard eb0b633
+
Mark Wielaard eb0b633
+	* elf_update.c (write_file): Always also use ftruncate before
Mark Wielaard eb0b633
+	posix_fallocate to make sure file has the right size.
Mark Wielaard eb0b633
+
Mark Wielaard eb0b633
 2015-06-04  Mark Wielaard  <mjw@redhat.com>
Mark Wielaard eb0b633
 
Mark Wielaard eb0b633
 	* elf_getdata.c (__libelf_type_aligns): Add entries for ELF_T_EHDR,
Mark Wielaard eb0b633
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
Mark Wielaard eb0b633
index 9e34c46..9eb007b 100644
Mark Wielaard eb0b633
--- a/libelf/elf_update.c
Mark Wielaard eb0b633
+++ b/libelf/elf_update.c
Mark Wielaard eb0b633
@@ -60,15 +60,18 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
Mark Wielaard eb0b633
      new file.  We truncate the file later in this case.
Mark Wielaard eb0b633
 
Mark Wielaard eb0b633
      Note we use posix_fallocate to make sure the file content is really
Mark Wielaard eb0b633
-     there. Using ftruncate might mean the file is extended, but space
Mark Wielaard eb0b633
+     there. Only using ftruncate might mean the file is extended, but space
Mark Wielaard eb0b633
      isn't allocated yet. This might cause a SIGBUS once we write into
Mark Wielaard eb0b633
      the mmapped space and the disk is full. Using fallocate might fail
Mark Wielaard eb0b633
      on some file systems. posix_fallocate is required to extend the file
Mark Wielaard eb0b633
      and allocate enough space even if the underlying filesystem would
Mark Wielaard eb0b633
-     normally return EOPNOTSUPP.  */
Mark Wielaard eb0b633
+     normally return EOPNOTSUPP.  Note that we do also need to ftruncate
Mark Wielaard eb0b633
+     in case the maximum_size isn't known and the file needs to be shorter
Mark Wielaard eb0b633
+     because posix_fallocate can only extend.  */
Mark Wielaard eb0b633
   if (elf->parent == NULL
Mark Wielaard eb0b633
       && (elf->maximum_size == ~((size_t) 0)
Mark Wielaard eb0b633
 	  || (size_t) size > elf->maximum_size)
Mark Wielaard eb0b633
+      && unlikely (ftruncate (elf->fildes, size) != 0)
Mark Wielaard eb0b633
       && unlikely (posix_fallocate (elf->fildes, 0, size) != 0))
Mark Wielaard eb0b633
     {
Mark Wielaard eb0b633
       __libelf_seterrno (ELF_E_WRITE_ERROR);
Mark Wielaard eb0b633
diff --git a/tests/ChangeLog b/tests/ChangeLog
Mark Wielaard eb0b633
index 19878ac..34f89cc 100644
Mark Wielaard eb0b633
--- a/tests/ChangeLog
Mark Wielaard eb0b633
+++ b/tests/ChangeLog
Mark Wielaard eb0b633
@@ -1,3 +1,8 @@
Mark Wielaard eb0b633
+2015-06-16  Mark Wielaard  <mjw@redhat.com>
Mark Wielaard eb0b633
+
Mark Wielaard eb0b633
+	* run-strip-test.sh: Add strip-in-place (eu-strip without -o) test
Mark Wielaard eb0b633
+	for non-ET_REL files.
Mark Wielaard eb0b633
+
Mark Wielaard eb0b633
 2015-05-30  Mark Wielaard  <mjw@redhat.com>
Mark Wielaard eb0b633
 
Mark Wielaard eb0b633
 	* backtrace-subr.sh (check_native_core): Notice core file couldn't be
Mark Wielaard eb0b633
diff --git a/tests/run-strip-test.sh b/tests/run-strip-test.sh
Mark Wielaard eb0b633
index c558e90..2ebb5a9 100755
Mark Wielaard eb0b633
--- a/tests/run-strip-test.sh
Mark Wielaard eb0b633
+++ b/tests/run-strip-test.sh
Mark Wielaard eb0b633
@@ -49,6 +49,19 @@ testrun ${abs_top_builddir}/src/unstrip -o testfile.unstrip testfile.temp testfi
Mark Wielaard eb0b633
 testrun ${abs_top_builddir}/src/elfcmp --hash-inexact $original testfile.unstrip
Mark Wielaard eb0b633
 }
Mark Wielaard eb0b633
 
Mark Wielaard eb0b633
+# Now strip in-place and make sure it is smaller.
Mark Wielaard eb0b633
+# Skip ET_REL files, they might have unexpected symbol table entries.
Mark Wielaard eb0b633
+is_ET_REL=0
Mark Wielaard eb0b633
+testrun ${abs_top_builddir}/src/readelf -h $original 2>&1 \
Mark Wielaard eb0b633
+  | fgrep 'REL (Relocatable file)' && is_ET_REL=1
Mark Wielaard eb0b633
+if test $is_ET_REL -eq 0; then
Mark Wielaard eb0b633
+  SIZE_original=$(stat -c%s $original)
Mark Wielaard eb0b633
+  testrun ${abs_top_builddir}/src/strip $original
Mark Wielaard eb0b633
+  SIZE_stripped=$(stat -c%s $original)
Mark Wielaard eb0b633
+  test $SIZE_stripped -lt $SIZE_original ||
Mark Wielaard eb0b633
+    { echo "*** failure in-place strip file not smaller $original"; status=1; }
Mark Wielaard eb0b633
+fi
Mark Wielaard eb0b633
+
Mark Wielaard eb0b633
 tempfiles testfile.sections
Mark Wielaard eb0b633
 testrun ${abs_top_builddir}/src/readelf -S testfile.temp > testfile.sections || status=$?
Mark Wielaard eb0b633
 fgrep ' .debug_' testfile.sections && status=1
Mark Wielaard eb0b633
-- 
Mark Wielaard eb0b633
1.8.3.1
Mark Wielaard eb0b633