15973e2
commit 47499e57d9321f4e45f33a3c1ab12264510ee7a4
15973e2
Author: Mark Wielaard <mark@klomp.org>
15973e2
Date:   Sat Jul 21 16:10:25 2018 +0200
15973e2
15973e2
    elfcompress: Swap fchmod and fchown calls on new file.
15973e2
    
15973e2
    Calling fchmod with a suid bit on a file might silently fail or the suid
15973e2
    bit might be slilently cleared by a call to fchown if already set. Swap
15973e2
    the calls so that the owner is set first and then set the suid bit.
15973e2
    
15973e2
    https://bugzilla.redhat.com/show_bug.cgi?id=1607044
15973e2
    
15973e2
    Signed-off-by: Mark Wielaard <mark@klomp.org>
15973e2
15973e2
diff --git a/src/elfcompress.c b/src/elfcompress.c
15973e2
index bdb0e3b..1a0f984 100644
15973e2
--- a/src/elfcompress.c
15973e2
+++ b/src/elfcompress.c
15973e2
@@ -1235,13 +1235,16 @@ process_file (const char *fname)
15973e2
   elf_end (elfnew);
15973e2
   elfnew = NULL;
15973e2
 
15973e2
-  /* Try to match mode and owner.group of the original file.  */
15973e2
-  if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
15973e2
-    if (verbose >= 0)
15973e2
-      error (0, errno, "Couldn't fchmod %s", fnew);
15973e2
+  /* Try to match mode and owner.group of the original file.
15973e2
+     Note to set suid bits we have to make sure the owner is setup
15973e2
+     correctly first. Otherwise fchmod will drop them silently
15973e2
+     or fchown may clear them.  */
15973e2
   if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
15973e2
     if (verbose >= 0)
15973e2
       error (0, errno, "Couldn't fchown %s", fnew);
15973e2
+  if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
15973e2
+    if (verbose >= 0)
15973e2
+      error (0, errno, "Couldn't fchmod %s", fnew);
15973e2
 
15973e2
   /* Finally replace the old file with the new file.  */
15973e2
   if (foutput == NULL)
15973e2
15973e2
commit d676c839e783996409d7845ea236e0883a827cbb
15973e2
Author: Mark Wielaard <mark@klomp.org>
15973e2
Date:   Sat Jul 21 17:07:12 2018 +0200
15973e2
15973e2
    elfcompress: Don't rewrite file if no section data needs to be updated.
15973e2
    
15973e2
    If the input and output file are the same and no section needs to
15973e2
    be updated we really don't need to rewrite the file. Check whether
15973e2
    any matching section is already compressed or (GNU) decompressed.
15973e2
    Skip the section if it doesn't need to be changed. If no section data
15973e2
    needs updating end with success without rewriting/updating file.
15973e2
    With --force the file will still always be updated/rewritten even if
15973e2
    no section data needs to be (de)compressed.
15973e2
    
15973e2
    Signed-off-by: Mark Wielaard <mark@klomp.org>
15973e2
15973e2
diff --git a/src/elfcompress.c b/src/elfcompress.c
15973e2
index 1a0f984..ae4708c 100644
15973e2
--- a/src/elfcompress.c
15973e2
+++ b/src/elfcompress.c
15973e2
@@ -1,5 +1,5 @@
15973e2
 /* Compress or decompress an ELF file.
15973e2
-   Copyright (C) 2015, 2016 Red Hat, Inc.
15973e2
+   Copyright (C) 2015, 2016, 2018 Red Hat, Inc.
15973e2
    This file is part of elfutils.
15973e2
 
15973e2
    This file is free software; you can redistribute it and/or modify
15973e2
@@ -286,6 +286,15 @@ process_file (const char *fname)
15973e2
     return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
15973e2
   }
15973e2
 
15973e2
+  /* How many sections are we going to change?  */
15973e2
+  size_t get_sections (void)
15973e2
+  {
15973e2
+    size_t s = 0;
15973e2
+    for (size_t i = 0; i < shnum / WORD_BITS + 1; i++)
15973e2
+      s += __builtin_popcount (sections[i]);
15973e2
+    return s;
15973e2
+  }
15973e2
+
15973e2
   int cleanup (int res)
15973e2
   {
15973e2
     elf_end (elf);
15973e2
@@ -422,6 +431,9 @@ process_file (const char *fname)
15973e2
      names change and whether there is a symbol table that might need
15973e2
      to be adjusted be if the section header name table is changed.
15973e2
 
15973e2
+     If nothing needs changing, and the input and output file are the
15973e2
+     same, we are done.
15973e2
+
15973e2
      Second a collection pass that creates the Elf sections and copies
15973e2
      the data.  This pass will compress/decompress section data when
15973e2
      needed.  And it will collect all data needed if we'll need to
15973e2
@@ -464,7 +476,26 @@ process_file (const char *fname)
15973e2
 
15973e2
       if (section_name_matches (sname))
15973e2
 	{
15973e2
-	  if (shdr->sh_type != SHT_NOBITS
15973e2
+	  if (!force && type == T_DECOMPRESS
15973e2
+	      && (shdr->sh_flags & SHF_COMPRESSED) == 0
15973e2
+	      && strncmp (sname, ".zdebug", strlen (".zdebug")) != 0)
15973e2
+	    {
15973e2
+	      if (verbose > 0)
15973e2
+		printf ("[%zd] %s already decompressed\n", ndx, sname);
15973e2
+	    }
15973e2
+	  else if (!force && type == T_COMPRESS_ZLIB
15973e2
+		   && (shdr->sh_flags & SHF_COMPRESSED) != 0)
15973e2
+	    {
15973e2
+	      if (verbose > 0)
15973e2
+		printf ("[%zd] %s already compressed\n", ndx, sname);
15973e2
+	    }
15973e2
+	  else if (!force && type == T_COMPRESS_GNU
15973e2
+		   && strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
15973e2
+	    {
15973e2
+	      if (verbose > 0)
15973e2
+		printf ("[%zd] %s already GNU compressed\n", ndx, sname);
15973e2
+	    }
15973e2
+	  else if (shdr->sh_type != SHT_NOBITS
15973e2
 	      && (shdr->sh_flags & SHF_ALLOC) == 0)
15973e2
 	    {
15973e2
 	      set_section (ndx);
15973e2
@@ -518,6 +549,14 @@ process_file (const char *fname)
15973e2
 	  }
15973e2
     }
15973e2
 
15973e2
+  if (foutput == NULL && get_sections () == 0)
15973e2
+    {
15973e2
+      if (verbose > 0)
15973e2
+	printf ("Nothing to do.\n");
15973e2
+      fnew = NULL;
15973e2
+      return cleanup (0);
15973e2
+    }
15973e2
+
15973e2
   if (adjust_names)
15973e2
     {
15973e2
       names = dwelf_strtab_init (true);