[Please keep myself and reproducible-builds@lists.alioth.debian.org in CC]

Hey,

Thomas Schmitt impressed upon me to send my work in progress patches
to make reproducible ISO images. I'm not 100% convinced by them all
but I guess it would be good to throw them over-the-wall and see what
you guys think.

They work for me in that I can make reproducible images for my usecases
if I export SOURCE_DATE_EPOCH (see below) and pass --modification-date
to xorriso. I haven't tested with any other emulator


0001-source_date_epoch.patch (libisoburn & libisofs)
----------------------------------------------------

See <https://reproducible-builds.org/specs/source-date-epoch/> for the
background and specification.

0002-set-target-now-from-source_date_epoch.patch (libisofs)
-----------------------------------------------------------

We seem to use IsoImage->now a fair amount, although I can't 100% recall
whether this is totally required given the other changes.

0002-set-default-timestamp.patch (libisoburn)
---------------------------------------------

Really not convinced by this change. Perhaps we should add another switch
like --modification-date. Or make modification-date default to S_D_E too?

0003-isohybrid-mbr.patch (libisofs)
-----------------------------------

Removes deliberate random number. It actually *slightly* weakens the
existing PRNG in the non-SOURCE_DATE_EPOCH case as I've dropped the usec
part but given that it was a terrible PRNG anyway and nobody is relying
on it for security, I think that's pretty safe. More secure to be
reproducible anyway.

0003-set-scdbackup_tag_time-from-source_date_epoch.patch (libisoburn)
---------------------------------------------------------------------

Obvious follow-on from 0001-source_date_epoch.patch.

0004-normalize-wday-yday.patch (libisoburn)
-------------------------------------------

Pretty uncontroversial in that you call asctime on an unnormalised tm
struct, so you end up with logging messages that always refer to
Sunday (ie. zero). Not needed for reproducibility but it was confusing
me when debugging..

Anyway, hope that helps.

(This work was sponsored by Webconverger.org.)


Regards,

-- 
      ,''`.
     : :'  :     Chris Lamb
     `. `'`      la...@debian.org / chris-lamb.co.uk
       `-
--- libisoburn-1.3.2.orig/libisoburn/isoburn.c
+++ libisoburn-1.3.2/libisoburn/isoburn.c
@@ -536,6 +536,11 @@ int isoburn_prepare_disc_aux(struct burn
                         opts->vol_creation_time, opts->vol_modification_time,
                         opts->vol_expiration_time, opts->vol_effective_time,
                         opts->vol_uuid);
+ if (getenv("SOURCE_DATE_EPOCH")) {
+   iso_write_opts_set_always_gmt(wopts, 1);
+   iso_write_opts_set_default_timestamp(wopts, Xorriso__current_time());
+   iso_write_opts_set_replace_timestamps(wopts, 2);
+ }
  iso_write_opts_attach_jte(wopts, opts->libjte_handle);
  iso_write_opts_set_hfsp_serial_number(wopts, opts->hfsp_serial_number);
 
--- libisoburn-1.3.2.orig/xorriso/misc_funct.c
+++ libisoburn-1.3.2/xorriso/misc_funct.c
@@ -463,6 +463,7 @@ int Decode_ecma119_format(struct tm *erg
 /* 2010040711405800 */
 {
  int i, l, num, utc= 1;
+ time_t normalized;
 
  memset(erg, 0, sizeof(*erg));
  erg->tm_isdst= -1;
@@ -499,6 +500,8 @@ int Decode_ecma119_format(struct tm *erg
  erg->tm_sec= 10*(text[12]-'0')+text[13]-'0';
  if(erg->tm_sec > 59)
    return(0);
+ normalized = mktime(erg);
+ erg = gmtime(&normalized);
  return(1 + !utc);
 }
 
--- libisoburn-1.3.2.orig/xorriso/write_run.c
+++ libisoburn-1.3.2/xorriso/write_run.c
@@ -945,7 +945,7 @@ int Xorriso_write_session(struct XorrisO
                              (gid_t) xorriso->global_gid);
  isoburn_igopt_set_out_charset(sopts, out_cs);
  isoburn_igopt_set_fifo_size(sopts, xorriso->fs * 2048);
- Ftimetxt(time(NULL), xorriso->scdbackup_tag_time, 8);
+ Ftimetxt(Xorriso__current_time(), xorriso->scdbackup_tag_time, 8);
  isoburn_igopt_set_scdbackup_tag(sopts, xorriso->scdbackup_tag_name,
                                  xorriso->scdbackup_tag_time,
                                  xorriso->scdbackup_tag_written);
--- libisoburn-1.3.2.orig/xorriso/misc_funct.c
+++ libisoburn-1.3.2/xorriso/misc_funct.c
@@ -22,6 +22,8 @@
 #include <sys/time.h>
 #include <time.h>
 #include <sys/utsname.h>
+#include <errno.h>
+#include <limits.h>
 
 
 #include "sfile.h"
@@ -1300,3 +1302,29 @@ int Xorriso__to_upper(char *in, char *ou
  return(in[i] == 0);
 }
 
+time_t Xorriso__current_time()
+{
+    char *source_date_epoch, *endptr;
+    time_t now = time(NULL);
+    unsigned long long epoch;
+
+    source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+
+    if (!source_date_epoch)
+        return now; 
+
+    errno = 0; 
+    epoch = strtoull(source_date_epoch, &endptr, 10); 
+
+    if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+            || (errno != 0 && epoch == 0))
+        return now; 
+    if (endptr == source_date_epoch)
+        return now; 
+    if (*endptr != '\0')
+        return now; 
+    if (epoch > ULONG_MAX)
+        return now; 
+
+    return (time_t)epoch;
+}
--- libisoburn-1.3.2.orig/xorriso/misc_funct.h
+++ libisoburn-1.3.2/xorriso/misc_funct.h
@@ -95,5 +95,7 @@ char *Xorriso__hide_mode_text(int hide_m
 */
 int Xorriso__to_upper(char *in, char *out, int out_size, int flag);
 
+time_t Xorriso__current_time();
+
 #endif /* ! Xorriso_pvt_misc_includeD */
 
--- libisofs-1.3.2.orig/libisofs/ecma119.c
+++ libisofs-1.3.2/libisofs/ecma119.c
@@ -1759,7 +1759,7 @@ int ecma119_image_new(IsoImage *src, Iso
     target->dir_mode = opts->replace_dir_mode == 2 ? opts->dir_mode : 0555;
     target->file_mode = opts->replace_file_mode == 2 ? opts->file_mode : 0444;
 
-    target->now = time(NULL);
+    target->now = iso_current_time();
     target->ms_block = opts->ms_block;
     target->appendable = opts->appendable;
 
--- libisofs-1.3.2.orig/libisofs/make_isohybrid_mbr.c
+++ libisofs-1.3.2/libisofs/make_isohybrid_mbr.c
@@ -27,6 +27,7 @@
 #include "ecma119.h"
 #include "eltorito.h"
 #include "system_area.h"
+#include "util.h"
 
 
 /* This code stems from syslinux-3.72/utils/isohybrid, a perl script
@@ -144,10 +145,6 @@ int make_isohybrid_mbr(int bin_lba, int
     char *wpt;
     off_t imgsize, cylsize, frac, padding, c, cc;
 
-    /* For generating a weak random number */
-    struct timeval tv;
-    struct timezone tz;
-
     if (bin_lba < 0 || bin_lba >= (1 << 29))
         return (0); /* 1 TB limit of signed 32 bit addressing of 512 byte blocks */
 
@@ -201,8 +198,7 @@ int make_isohybrid_mbr(int bin_lba, int
      from. An environment variable ?
      125: Whatever, i use some 32-bit random value with no crypto strength.
      */
-    gettimeofday(&tv, &tz);
-    id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000));
+    id = 0xffffffff & iso_current_time();
 
     /*
      126: Adds 4 id bytes and 2 zero bytes.
@@ -566,9 +562,6 @@ int make_isolinux_mbr(int32_t *img_block
     uint32_t boot_lba, mbr_id;
     int head_count, sector_count, ret;
     int gpt_count = 0, gpt_idx[128], apm_count = 0, gpt_cursor;
-    /* For generating a weak random number */
-    struct timeval tv;
-    struct timezone tz;
 
     hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
 
@@ -605,8 +598,7 @@ int make_isolinux_mbr(int32_t *img_block
        (here some 32-bit random value with no crypto strength)
     */
     if (flag & 1) {
-        gettimeofday(&tv, &tz);
-        id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000));
+        id = 0xffffffff & iso_current_time();
         lsb_to_buf(&wpt, id, 32, 0);
     }
 
--- libisofs-1.3.2.orig/libisofs/util.c
+++ libisofs-1.3.2/libisofs/util.c
@@ -1401,6 +1401,33 @@ uint32_t iso_read_bb(const uint8_t *buf,
     return v1;
 }
 
+time_t iso_current_time()
+{
+    char *source_date_epoch, *endptr;
+    time_t now = time(NULL);
+    unsigned long long epoch;
+
+    source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+
+    if (!source_date_epoch)
+        return now; 
+
+    errno = 0; 
+    epoch = strtoull(source_date_epoch, &endptr, 10); 
+
+    if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+            || (errno != 0 && epoch == 0))
+        return now; 
+    if (endptr == source_date_epoch)
+        return now; 
+    if (*endptr != '\0')
+        return now; 
+    if (epoch > ULONG_MAX)
+        return now; 
+
+    return (time_t)epoch;
+}
+
 void iso_datetime_7(unsigned char *buf, time_t t, int always_gmt)
 {
     static int tzsetup = 0;
--- libisofs-1.3.2.orig/libisofs/util.h
+++ libisofs-1.3.2/libisofs/util.h
@@ -244,6 +244,8 @@ uint32_t iso_read_msb(const uint8_t *buf
  */
 uint32_t iso_read_bb(const uint8_t *buf, int bytes, int *error);
 
+time_t iso_current_time();
+
 /** 
  * Records the date/time into a 7 byte buffer (ECMA-119, 9.1.5)
  * 
_______________________________________________
Reproducible-builds mailing list
Reproducible-builds@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reproducible-builds

Reply via email to