[BUG] e2fsck: ignores SOURCE_DATE_EPOCH / E2FSPROGS_FAKE_TIME for s_lastcheck

Levi Shafter <[email protected]>
Newsgroups org.kernel.vger.linux-ext4
Message-ID <[email protected]>
Sponsor: 21SoftWare LLC

Version: e2fsprogs 1.47.1 (also 1.47.0)

Summary

mke2fs and the ext2fs library honor SOURCE_DATE_EPOCH (and
E2FSPROGS_FAKE_TIME) for filesystem timestamps, but e2fsck does not. A
check pass therefore writes the current wall-clock time into the
superblock's last-check time (s_lastcheck) and last-write time
(s_wtime), so running e2fsck as part of a reproducible image build
produces a different filesystem on every run.

Details

lib/ext2fs/openfs.c sets fs->now from SOURCE_DATE_EPOCH /
E2FSPROGS_FAKE_TIME when opening a filesystem. e2fsck, however,
initializes its
own clock without consulting those variables and then uses it for the
superblock:

- e2fsck/e2fsck.c (e2fsck_allocate_context): context->now =
getenv("E2FSCK_TIME") ? strtoull(...) : time(0);
- e2fsck/unix.c: fs->now = ctx->now; (overwrites the library's value)
- e2fsck/unix.c: ext2fs_set_tstamp(sb, s_lastcheck, ctx->now);

An E2FSCK_TIME override already exists, so the mechanism is in place —
it's just not tied to the reproducibility variables the rest of the
suite uses.

Steps to Reproduce

dd if=/dev/zero of=test.img bs=1M count=16
SOURCE_DATE_EPOCH=1000000000 mke2fs -t ext4 -F -q test.img
SOURCE_DATE_EPOCH=1000000000 e2fsck -fy test.img >/dev/null
dumpe2fs -h test.img | grep -E 'Filesystem created|Last checked|Last write'

Actual: Filesystem created = 2001-09-09 (mke2fs honored the epoch), but
Last checked / Last write time = the current date (e2fsck used
time(0)).
Expected: with SOURCE_DATE_EPOCH set, all three reflect the epoch.

Impact

Reproducible-build pipelines (e.g. Yocto/OpenEmbedded) that run fsck
during image creation get non-reproducible ext2/3/4 images.
OpenEmbedded's wic currently works around this with a post-fsck debugfs
set_super_value pass.

Suggested fix

In e2fsck_allocate_context, when E2FSCK_TIME is unset, fall back to
SOURCE_DATE_EPOCH (and/or E2FSPROGS_FAKE_TIME) before time(0), matching
lib/ext2fs. Roughly:

time_env = getenv("E2FSCK_TIME");
if (!time_env)
	  time_env = getenv("SOURCE_DATE_EPOCH");
if (time_env)
	  context->now = (time_t) strtoull(time_env, NULL, 0);
else {
	  context->now = time(0);
	  if (context->now < 1262322000) /* January 1 2010 */
			  context->flags |= E2F_FLAG_TIME_INSANE;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.