* [BUG] e2fsck: ignores SOURCE_DATE_EPOCH / E2FSPROGS_FAKE_TIME for s_lastcheck
@ 2026-08-10 17:56 Levi Shafter
2026-09-06 0:09 ` Theodore Tso
0 siblings, 1 reply; 2+ messages in thread
From: Levi Shafter @ 2026-08-10 17:56 UTC (permalink / raw)
To: linux-ext4; +Cc: tytso
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;
}
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [BUG] e2fsck: ignores SOURCE_DATE_EPOCH / E2FSPROGS_FAKE_TIME for s_lastcheck
2026-08-10 17:56 [BUG] e2fsck: ignores SOURCE_DATE_EPOCH / E2FSPROGS_FAKE_TIME for s_lastcheck Levi Shafter
@ 2026-09-06 0:09 ` Theodore Tso
0 siblings, 0 replies; 2+ messages in thread
From: Theodore Tso @ 2026-09-06 0:09 UTC (permalink / raw)
To: Levi Shafter; +Cc: linux-ext4
On Mon, Aug 10, 2026 at 11:56:11AM -0500, Levi Shafter wrote:
> 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.
Thanks for the report. This patch should address your concerns.
- Ted
commit fa70a99daf14a98b2b67d85010942de4f6a937b6
Author: Theodore Ts'o <tytso@mit.edu>
Date: Sat Sep 5 17:50:32 2026 -0400
e2fsck: support SOURCE_DATE_EPOCH and E2FSPROGS_FAKE_TIME env variables
Some projects use SOURCE_DATE_EPOCH the environment variable per the
recommendations in [1] to create reproducible artifacts. If those
projects use e2fsck to check a generated file system before running
tune2fs or resize2fs, the current time will get used in some
superblock fields, thus making it no longer be reproducible.
[1] https://reproducible-builds.org/specs/source-date-epoch
Setting the E2FSCK_TIME environment variable will address this issue,
but it's confusing that e2fsck requires that both environment
variables needs to be set.
Fix this by teaching e2fsck to support SOURCE_DATE_EPOCH and
E2FSPROGS_FAKE_TIME environment variables to work alongside
E2FSCK_TIME, and setting any one of these three environment variables
should be sufficient to address all changes made by e2fsck.
Reported-by: Levi Shafter <levi.shafter@elder-tomes.com>
Link: https://lore.kernel.org/r/4c130a23-7283-45a9-852a-b24ed78eb0d1@elder-tomes.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c
index 1e295e3ef..18dd2569e 100644
--- a/e2fsck/e2fsck.c
+++ b/e2fsck/e2fsck.c
@@ -36,6 +36,10 @@ errcode_t e2fsck_allocate_context(e2fsck_t *ret)
context->htree_slack_percentage = 255;
time_env = getenv("E2FSCK_TIME");
+ if (!time_env)
+ time_env = getenv("SOURCE_DATE_EPOCH");
+ if (!time_env)
+ time_env = getenv("E2FSPROGS_FAKE_TIME");
if (time_env)
context->now = (time_t) strtoull(time_env, NULL, 0);
else {
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index 7768f0ed7..4de7bf78d 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -1211,6 +1211,7 @@ static errcode_t try_open_fs(e2fsck_t ctx, int flags, io_manager io_ptr,
if (retval == 0) {
(*ret_fs)->priv_data = ctx;
+ (*ret_fs)->now = ctx->now;
e2fsck_set_bitmap_type(*ret_fs, EXT2FS_BMAP64_RBTREE,
"default", NULL);
}
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-06 0:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-10 17:56 [BUG] e2fsck: ignores SOURCE_DATE_EPOCH / E2FSPROGS_FAKE_TIME for s_lastcheck Levi Shafter
2026-09-06 0:09 ` Theodore Tso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox