]> git.wh0rd.org Git - elf2flt.git/commitdiff
elf2flt.c: add support for SOURCE_DATE_EPOCH
authorThomas Petazzoni <thomas.petazzoni@bootlin.com>
Fri, 27 Dec 2019 15:40:42 +0000 (16:40 +0100)
committerMike Frysinger <vapier@gmail.com>
Sun, 29 Dec 2019 14:12:08 +0000 (19:57 +0545)
The bFLT header has a "build_date" field which contains the date/time
at which the bFLT file was created. Unfortunately, this breaks
reproducible builds as two identical builds done at different times
will produce different results.

For example, on a bFLT binary, diffoscope reports the following
change:

  00000000: 6246 4c54 0000 0004 0000 0045 0001 48d4  bFLT.......E..H.
  00000010: 0002 85a0 0002 fe50 0000 1000 0002 85a0  .......P........
 -00000020: 0000 0757 0000 0001 5e05 742e 0000 0000  ...W....^.t.....
 +00000020: 0000 0757 0000 0001 5e05 a5c2 0000 0000  ...W....^.......

In order to address this, this commit adds support for the
SOURCE_DATE_EPOCH environment variable, which is standardized by the
reproducible-builds.org group at
https://reproducible-builds.org/specs/source-date-epoch/.

We simply use the time from the SOURCE_DATE_EPOCH variable (which
contains the number of seconds since Epoch) when SOURCE_DATE_EPOCH is
available in the environment, and otherwise fallback to the existing
logic that takes the current time using time().

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
elf2flt.c

index 8973cef179feb3c230d0d1b0f861d14f307c1ae1..b7c4a490df02be746fcc72b593b06aa14f685a9d 100644 (file)
--- a/elf2flt.c
+++ b/elf2flt.c
@@ -46,6 +46,7 @@
 #include <unistd.h>   /* Userland prototypes of the Unix std system calls    */
 #include <fcntl.h>    /* Flag value for file handling functions              */
 #include <time.h>
+#include <errno.h>
 
 /* from $(INSTALLDIR)/include       */
 #include <bfd.h>      /* Main header file for the BFD library                */
@@ -1689,6 +1690,31 @@ static void write_zeroes (unsigned long num, stream *stream)
 }
 
 
+static time_t get_build_date(void)
+{
+  const char *sde;
+  unsigned long long epoch;
+  char *endptr;
+
+  sde = getenv("SOURCE_DATE_EPOCH");
+  if (!sde)
+    return time(NULL);
+
+  /* Largely inspired from
+     https://reproducible-builds.org/docs/source-date-epoch/ */
+  errno = 0;
+  epoch = strtoull(sde, &endptr, 10);
+  if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+      || (errno != 0 && epoch == 0)
+      || (endptr == sde)
+      || (*endptr != '\0')
+      || (epoch > ULONG_MAX))
+    fatal("Invalid SOURCE_DATE_EPOCH value");
+
+  return (time_t)epoch;
+}
+
+
 int main(int argc, char *argv[])
 {
   int fd;
@@ -1948,7 +1974,7 @@ int main(int argc, char *argv[])
          | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
          | (docompress ? (docompress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
          );
-  hdr.build_date = htonl((uint32_t)time(NULL));
+  hdr.build_date = htonl((uint32_t)get_build_date());
   memset(hdr.filler, 0x00, sizeof(hdr.filler));
 
   for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);