Ever wondered if that raspi is actually running the code it’s supposed to? Today we’re taking Alpine Linux as a base and trying to make a reproducible image, so an independent party can verify the image is legitimately built from source. All patches are going to be sent upstream.

It’s mostly mtimes, so we’re starting by editing ./mkimg.base.sh and introducing SOURCE_DATE_EPOCH support to normalize it. After that diffoscope shows 3 files that actually differ in content. We’re going to focus on the initramfs first and look into the APKINDEX.tar.gz later.

This turned out slightly tricky, we’re excluding rpi2 support to cut down build time and speed up testing, you can see that there are non-normalized mtimes inside the initramfs files again. We’re now also striping the build-user uid and user name from the image.

We’ve now normalized the mtime in the cpio as well, according to diffoscope the cpio content is now identical, but the raw binary of the cpio files is not. Next up is downloading a cpio parser lib and the busybox source to figure out what those bytes mean and how to fix them.

The script used to test all this is here (Gist).

The first two patches have been submitted:

In the hex dump we see the first difference is at 0x9, we assume that’s probably within the first entry. We quickly hack together a basic debugger with rust to dump all fields with @jcreekmore’s cpio crate and confirm our theory. ino is the inode number of the input file.

The code for that has been very quickly thrown together and is a combination of code lifted from the libraries’ examples/ folder, text pasted from docs.rs and vim visual block editing proficiency.

Alpine uses busybox, so this is the relevant code in cpio.c. It’s reading the inode number directly from a struct, if we trace it back we can see it’s getting populated with one of the stat syscalls. There’s unfortunately no way to override st_ino so this is a dead-end for now.

Alright, we’re about to wrap this up for today, but we promised to look into APKINDEX.tar.gz too. As you can see those files are identical except the modification time. This is a trivial fix in abuild but there’s one catch: This file is usually signed.

Since the signature is basically a random blob by design we’ve temporarily disabled this earlier. A rebuilder would likely copy over the signature, and at that point they might as well copy the index as a whole. Or they won’t, didn’t really think about the implications yet.

No idea how to write an outro, if you’re into applied reproducible builds you might also enjoy rebuilderd. We’d also like to point out that - since we’re kinda shy - we can’t apply for grants. Sponsoring goes a long way though. Thanks!

This post was originally published on Twitter.