From patchwork Tue Oct 13 10:49:35 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Kiernan X-Patchwork-Id: 100592 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1724ACC6B0F for ; Tue, 13 Oct 2026 10:50:00 +0000 (UTC) Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4138.1791888593430647341 for ; Tue, 13 Oct 2026 03:49:53 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=VwCdGmUP; spf=pass (domain: gmail.com, ip: 209.85.128.51, mailfrom: alex.kiernan@gmail.com) Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4a1af482519so3040025e9.1 for ; Tue, 13 Oct 2026 03:49:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791888592; x=1792493392; darn=lists.openembedded.org; h=to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=AK/uWSjjtGdavCBo8VsVKJZZtIeP0KmAsZabSknCgBs=; b=VwCdGmUPrYIMoF9E5VTsEfBe0lFon0Ib0swSEBOP3Cqd8nFS9EMB+jnh2jynWjkVQ5 zO9dgMavlEbsnj0++vh8gxlRs3FH18a+zRMqGQNMtzSKjK2CloeROLs456M/TweXgCcw fdCekAzGSeMvgeHvgJ1wh9CPqQ/Jo+IOITPlesd+wfdDjsqsRa7sFeKCL6ky5QEYG36O VpytwZgNxehVntSdl8rPeljkALPNcuR4EOdZ73HfCD/ULnZJrZ83po9gwyxPtoEyF2a/ Cas/CrGJJ78laxJCM954j0ev/h08EvBrnZxKFvWyTmTEC+w3xniLYi0an5GLuDjGFig+ b7xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791888592; x=1792493392; h=to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=AK/uWSjjtGdavCBo8VsVKJZZtIeP0KmAsZabSknCgBs=; b=hblVUTTFXkLTvFjtJLBSLyH8qeg0myilFfuDSwgG0TnpRb8+awJlPnsKztTWBpjhMF 59U0kPZ217fzz04FIe+s0RDZW6kJzKbwH8bwCHRNvoN/i/wp6pIgatdElhxzCQzcbdkX n3e2sSJakJZ9PdVhcWMEFQrJ4HdUf7zNaA8hC/uBoCt/xdey5v4TW8GREJHdEAnkDGRX Hg8XrKdL6rP1oQCCBJ4zkRsL3iEDsZy8gZ77PEXXV9LJ0GbMHmY5KdgNVZt5g43lhjp5 Otl6C+KK5XDCeHEVoVVgiIPgwrNU1BlFDk4RJy27arEKVMZo8QS1WOgCvvMpD4zsZHWN w95g== X-Gm-Message-State: AFq9FYKJJNmz5Eki/lUKLnKk9NfYdmAouLEuEV8aR4SuDRre16zbO1Nn IUAMDqVBICmkPWMkOKN9ezwNQS3VxaI95NCTaL3/mgAp6Ajq7vGaampYWqbq3w== X-Gm-Gg: AYBFou1M4cwIPh9kjfZzq73jI3ISG3tbhxfqxmbEHhipfBqcPrVECmhGRPAoniDzIOZ qzn1GiYHI9HN2IWj7znOFrp+TsADU69xfA9aQwKvY+Uj5W/knSzvFAnLFNNKvDUUkBur2gymM8p 9SX7oulpdrJvuId1Tp1mnKHtzzGWYFMajSvPrZOjL+c1FBwgrfswazO64c/sSPKKtzgn8gAdkjR 8ia9HuLoV7knINXgDw9QzCo822fg1pcW8cnkLjiL/4zXlbbch3yc7EfTt0ocOB/Hva8v325o8Me +yIIcPOSp6YZQTCi3S/jwmwY6v18tCgW9+CFKvVvEqKgvETkUHHdjix9HyZ85WJQ0FVF60UlL+2 IFJk0AonqxcvB66kiAkwAkhELEJNwi82vnTDHElrHLlSc+nyYrkyfX9RXRrI1TajRkKZjrrRT5E 4Ayju5s1hmV6Zmnbj+8Go1GPGyhYllnzHoOLsUwj6oP70mZ+sjrqU8lJAMYqP/9DDeP9JXqK70v I0OWzyR5UXOEmOf1gOOix0dv+6UlBVBuGdieNE1ubWL8gv5lg== X-Received: by 2002:a05:600c:8b78:b0:49e:65f2:db64 with SMTP id 5b1f17b1804b1-4a18e4837f2mr226002105e9.5.1791888591536; Tue, 13 Oct 2026 03:49:51 -0700 (PDT) Received: from [192.168.5.15] (cust18-dsl93-89-130.idnet.net. [93.89.130.18]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a19303d4a9sm31623155e9.2.2026.10.13.03.49.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Oct 2026 03:49:49 -0700 (PDT) From: Alex Kiernan Date: Tue, 13 Oct 2026 11:49:35 +0100 Subject: [PATCH 1/4] package_manager: pass REPRODUCIBLE_TIMESTAMP_ROOTFS to intercepts MIME-Version: 1.0 Message-Id: <20261013-fontcache-reproducible-mtime-v1-1-950f07b80f0f@gmail.com> References: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> In-Reply-To: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> To: openembedded-core@lists.openembedded.org X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 13 Oct 2026 10:50:00 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247717 do_rootfs marks REPRODUCIBLE_TIMESTAMP_ROOTFS for export, but that only reaches the shell functions it emits afterwards. The task's environment is fixed when it starts, so the postinst intercepts, which run from it, never see the timestamp every file in the image will end up with. Set it alongside D and STAGING_DIR_NATIVE. AI-Generated: Claude Opus 5.5 (Claude Code) --- meta/lib/oe/package_manager/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py index 88bc5ab19520..76289c911b0b 100644 --- a/meta/lib/oe/package_manager/__init__.py +++ b/meta/lib/oe/package_manager/__init__.py @@ -223,6 +223,12 @@ class PackageManager(object, metaclass=ABCMeta): bb.note("Running intercept scripts:") os.environ['D'] = self.target_rootfs os.environ['STAGING_DIR_NATIVE'] = self.d.getVar('STAGING_DIR_NATIVE') + # The mtime every file in the image will end with; intercepts that + # record an mtime need it, and do_rootfs only exports it to shell + # functions it emits, not to the environment they run in. + timestamp = self.d.getVar('REPRODUCIBLE_TIMESTAMP_ROOTFS') + if timestamp: + os.environ['REPRODUCIBLE_TIMESTAMP_ROOTFS'] = timestamp for script in os.listdir(intercepts_dir): script_full = os.path.join(intercepts_dir, script) From patchwork Tue Oct 13 10:49:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Kiernan X-Patchwork-Id: 100593 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id AAB31CC6B03 for ; Tue, 13 Oct 2026 10:49:59 +0000 (UTC) Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4062.1791888595851966565 for ; Tue, 13 Oct 2026 03:49:56 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=q6zRAd3D; spf=pass (domain: gmail.com, ip: 209.85.128.41, mailfrom: alex.kiernan@gmail.com) Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-4a16c1608faso36366925e9.0 for ; Tue, 13 Oct 2026 03:49:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791888594; x=1792493394; darn=lists.openembedded.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=PQaPQGXMJ68Ym6L+LX3oDVCci+yREZ8PSjEVnbCV5I8=; b=q6zRAd3DlLIy/x5Bu9qHKbNAZibMmLEeCFk0dkZCudo2qTvLrwKVQ8fEM9DijeO4Q0 J12MwabE23ovsi3uwfFsY9m8PktKr0nSA0aN4zILdxOhDlG698NeE5hJPcfhEMEumdPx hHma943auOC+tPv/lxgU6mUXxdqspmxYyZyqhSVuDJi1d4WC7huTYFFtymbExmbp5drf 7Or6qvW4+V5wj3T5gnTooFKFNrruVMYb/NIC89VPWmKC+S2q9j46m7B0fmJ/sTZkR1yj xCMXfxgvutYjuM3jBMSSGbQsuM1kBiJ2dySui8bXU0y4nCYebnFHIpz05YYndhI6KZmt 4mRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791888594; x=1792493394; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=PQaPQGXMJ68Ym6L+LX3oDVCci+yREZ8PSjEVnbCV5I8=; b=PqZiLOrogAkG1Drl3k26a6H4r4n3C2CguKisSStWjrD0FalVNHfIKDg9FeAzyPSo/v Oa71baAP4yk5Ox4qalYhc86Mnw3zA5h82QIKD7/gF1+8sIunSWBFMBNaiUBOHsPOth4H BxTMAnQZhjV+ZjClYY/El9ZlUrk5sovQIFAoVUABORoP4GoPA6tE5bi7TV53wiJnRllw 4RKx0oJBB17dz0YUpUClYw7veyBU1qq4SfltpvewkA5aMbfNQ8/Gn29MiSozMqc5lPLB apbH6rseGA7KfGDp/p/tae9UpyWSc4sGrWZCTtF3Yu9mgFDebDQoaZ0zlgjZ54zDr+Q9 iukg== X-Gm-Message-State: AFq9FYLCK4KAZkXHmeABPeoJFQjuCrP+rMdS8WYNBMH3ryhNrCX2hsAS pVEWfOCG60nuf7DQjNi2sUnW80lRIbdvuPoadsFd6ca6yZYFz3+pmgQoNz0urQ== X-Gm-Gg: AYBFou3RKH90N8A7hXGEocH/hlK4ekmGKWcCyWN1BWPlfSo0nvlHuRmHYwuZanxxZkr GvtnuFSJ6cJErYxYvKYOJlfHfm2ucGg79k2qlQOznyQcQjdh5NQLrJ2Hw1jn22rLhkBsr+D01ks n7kE1esSYurcRGtDr825sbPy6pfK5GJvL/+Fp3EF7Fyn+Zs2E01QOCB+V+DOgLQMBMdglvFaE6A CdxZZJIHzNLAP7e+MaVduFqzvWMDXJuvyPDbHZ5IE5RGlLhYyscujKTtrlco0+B9JS5Ne0wheJ+ 7hZAifRNgNpP6Y4N8t05FEYt63M+PcpPTcIALLa99kfb6/GASrw2KawSt86kHZv0ZeaM2IRcTbj 5EXM2W10K8YiWa9T0FmxERHeDc8G4cs8ofYARHW5jLzV1GD5HFYMInnA04ASPhUfwa9OBJQRwGQ Bj+B253fn/zygEmAnUA4Qs0JcbQrIuJe41CazIi9ly0vY5o2Q7uFKDMLfw1TG+eYdxZMy7UZkQi jeVOhe1TGBGdzyOfWhLdxA3jDw592VdVaw39/UQpFhIw6MTDw== X-Received: by 2002:a05:600c:4e92:b0:49e:63cc:6324 with SMTP id 5b1f17b1804b1-4a18e4837e7mr237221165e9.6.1791888594054; Tue, 13 Oct 2026 03:49:54 -0700 (PDT) Received: from [192.168.5.15] (cust18-dsl93-89-130.idnet.net. [93.89.130.18]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a19303d4a9sm31623155e9.2.2026.10.13.03.49.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Oct 2026 03:49:51 -0700 (PDT) From: Alex Kiernan Date: Tue, 13 Oct 2026 11:49:36 +0100 Subject: [PATCH 2/4] update_font_cache: write caches that are valid in the final image MIME-Version: 1.0 Message-Id: <20261013-fontcache-reproducible-mtime-v1-2-950f07b80f0f@gmail.com> References: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> In-Reply-To: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> To: openembedded-core@lists.openembedded.org Cc: Alex Kiernan X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 13 Oct 2026 10:49:59 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247718 fontconfig accepts a directory's cache only while the mtime recorded in it matches the directory, and fc-cache records the mtime clamped to SOURCE_DATE_EPOCH. The intercept runs with the image's SOURCE_DATE_EPOCH, against font directories that still carry their packages' mtimes, and reproducible_final_image_task later sets every mtime in the image to REPRODUCIBLE_TIMESTAMP_ROOTFS. The recorded and final mtimes never match, so on the target every cache the image ships is rejected and each process using fontconfig rescans the fonts and writes a cache of its own. When REPRODUCIBLE_TIMESTAMP_ROOTFS is set, set the mtime of every directory under ${datadir}/fonts to it before running fc-cache, and run fc-cache with it as SOURCE_DATE_EPOCH, so the caches record the mtimes the image ships with. AI-Generated: Claude Opus 5.5 (Claude Code) Signed-off-by: Alex Kiernan --- meta/classes-recipe/fontcache.bbclass | 1 + scripts/postinst-intercepts/update_font_cache | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/meta/classes-recipe/fontcache.bbclass b/meta/classes-recipe/fontcache.bbclass index deadcd2fbbeb..37ff7d7cbc7e 100644 --- a/meta/classes-recipe/fontcache.bbclass +++ b/meta/classes-recipe/fontcache.bbclass @@ -28,6 +28,7 @@ if [ -n "$D" ] ; then 'libdir="${libdir}"' \ 'libexecdir="${libexecdir}"' \ 'base_libdir="${base_libdir}"' \ + 'datadir="${datadir}"' \ 'fontconfigcachedir="${FONTCONFIG_CACHE_DIR}"' \ 'fontconfigcacheparams="${FONTCONFIG_CACHE_PARAMS}"' \ 'fontconfigcacheenv="${FONTCONFIG_CACHE_ENV}"' diff --git a/scripts/postinst-intercepts/update_font_cache b/scripts/postinst-intercepts/update_font_cache index 900db042d64e..5098b2890cc8 100644 --- a/scripts/postinst-intercepts/update_font_cache +++ b/scripts/postinst-intercepts/update_font_cache @@ -7,7 +7,17 @@ set -e rm -f $D${fontconfigcachedir}/CACHEDIR.TAG -PSEUDO_UNLOAD=1 ${binprefix}qemuwrapper -L $D -E ${fontconfigcacheenv} $D${libexecdir}/${binprefix}fc-cache --sysroot=$D --system-only ${fontconfigcacheparams} +# fontconfig only uses a cache while the mtime it recorded for a font +# directory, clamped to SOURCE_DATE_EPOCH, matches the directory. Every +# mtime in the image is set to REPRODUCIBLE_TIMESTAMP_ROOTFS later, so set +# the font directories' mtimes to it now and have fc-cache record that. +sde= +if [ -n "$REPRODUCIBLE_TIMESTAMP_ROOTFS" ] && [ -d $D${datadir}/fonts ]; then + find $D${datadir}/fonts -type d -exec touch -h --date=@$REPRODUCIBLE_TIMESTAMP_ROOTFS '{}' + + sde="-E SOURCE_DATE_EPOCH=$REPRODUCIBLE_TIMESTAMP_ROOTFS" +fi + +PSEUDO_UNLOAD=1 ${binprefix}qemuwrapper -L $D -E ${fontconfigcacheenv} $sde $D${libexecdir}/${binprefix}fc-cache --sysroot=$D --system-only ${fontconfigcacheparams} chown -R root:root $D${fontconfigcachedir} find $D -type f -name .uuid -exec chown root:root '{}' + From patchwork Tue Oct 13 10:49:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Kiernan X-Patchwork-Id: 100591 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 901FBCA9ED2 for ; Tue, 13 Oct 2026 10:49:59 +0000 (UTC) Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4063.1791888597742348453 for ; Tue, 13 Oct 2026 03:49:58 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=gA8S41pQ; spf=pass (domain: gmail.com, ip: 209.85.128.54, mailfrom: alex.kiernan@gmail.com) Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4a140e7405dso32174795e9.3 for ; Tue, 13 Oct 2026 03:49:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791888596; x=1792493396; darn=lists.openembedded.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=DxvmEM7UOhdACm+/m/zyjMu+RKcGOpVLO3q3LpXOZaQ=; b=gA8S41pQ4r/DDSo/n5ruffIlKabPm0Vx9TO0EePwLe45wIUYSqlBZg7NvI0T7ubul5 4nKYERlOoBinG7sgGkEJutT0H5HupNfNdNHjtR1igm1FWBTuguXYmZ1UEgLVEuFk5t37 F9QVILXA33Akttpqn2/tLjJTdkaY5SXkBrvECc1asiZzYS+JS0xq5v71K1IqwtIHKxGY GmSfUDj4j2OsuiEPc4fxYlTn/9/kBk98YymgZzL13+3krKBcTxsFj9TrphycxZsHxLL7 tkwxprvbAD267B9TL9Oqt+iDXPmZsSz7xa4OEfWJ6VZM7x3Fu/y1cgmSFFkUMGxWTfPX ZVGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791888596; x=1792493396; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=DxvmEM7UOhdACm+/m/zyjMu+RKcGOpVLO3q3LpXOZaQ=; b=LYRO4V/m/G/nBBhT3TgWYY9cgLPk1du26O2moDKGM8f4Mhi5/UwaBzRjR7eRi6Ix5a roiRmqt7f+1DRnIbwV5xFKY3hwsWm+VkGhQc9ruube5kMcqFLBrmDEI4uFjoOQ52q2Ej COrH1mwI+EchIpKRzlyBP58gnvxRp9ES/uawataK/TnGfUkv9zJ977+RWx3xsHn/uhB9 /P2Sr9576KRxrlmH1Dg8uV4GDzP8iWsN79elFNr2XM4DurUT8hW0/40Ml5qKlCF8cJx+ sIh4A2LBIEISiKfL4nCVIRUxw1O8vEez2F6slb0JafiKl00SDWNVDeSL9qZuZvYhGMtu RVmw== X-Gm-Message-State: AFq9FYIVnvGZnVVDhRhafs9EdFr+1MtvFbAMiEsWl5J7iME/8M880akT WlnLMNEAN4JHEv9l+Zwt4+Y52p73EbsTwNHClqL6QuDYYmR5bTU18A7A+WlFDA== X-Gm-Gg: AYBFou0URfR1/meEGD64bKHc38iQ+CnBhG6/9FrtI4CVmFvBnnxsCjXZ0CNPMbQb+mT cFJzR5QSX7xBiAJ0j6l+2h8qvXCSjI+f//tPJvJWfQfCpb2JDg8uIOK1Vo6Ur6bw8Hu+FolfpfG fjybnXMX9NkAvclTny09VZ7FOE7eF+PKbS7tL51NbQw7FRa9YlKFOxdcBvBaOWlNjRyZuGfuPBU TZNKxLldAuT2OAII2gOKP18hm3yEhjQmkXS/Z6DI9O7OixhZocmh02G3SqTu7Yz+fw9DlnwuXsk gqkPCJ1N9T9OaXok4qDvxe3dQGix48jazflYQgf9iE+3O3V+Bx+nsZUvQ2yt+MHtH65YCkcqfVm AiEXH53qfkwYC6nnxAD/aLO3tJKdNFCbIUUI786L+h6WNwE7F/Xa2h4XjdUfLhDFSu96G33nbpr JmElfHlNAApUusSkhHCforY9bjXVAQgc05OVlGGjn+zLAUkNx6Aw4RFO58nAUAFkuHtc0lIgR7r JDQ9bSIc8oun17x94ZfJAT/ohI1yhrfm50ix8QBVQh90tH9dWj8v+bC9KoK X-Received: by 2002:a05:600c:4ecb:b0:4a1:6916:798 with SMTP id 5b1f17b1804b1-4a18e4a3f69mr234454985e9.14.1791888595639; Tue, 13 Oct 2026 03:49:55 -0700 (PDT) Received: from [192.168.5.15] (cust18-dsl93-89-130.idnet.net. [93.89.130.18]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a19303d4a9sm31623155e9.2.2026.10.13.03.49.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Oct 2026 03:49:54 -0700 (PDT) From: Alex Kiernan Date: Tue, 13 Oct 2026 11:49:37 +0100 Subject: [PATCH 3/4] image_types: keep the rootfs mtimes in ext2/3/4 images MIME-Version: 1.0 Message-Id: <20261013-fontcache-reproducible-mtime-v1-3-950f07b80f0f@gmail.com> References: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> In-Reply-To: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> To: openembedded-core@lists.openembedded.org Cc: Alex Kiernan X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 13 Oct 2026 10:49:59 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247719 mke2fs reads SOURCE_DATE_EPOCH from the environment and clamps the time of every inode it creates to it. bitbake exports the image's SOURCE_DATE_EPOCH, which is older than the REPRODUCIBLE_TIMESTAMP_ROOTFS that reproducible_final_image_task gives every file, so an ext image carries different mtimes from a tar or squashfs image of the same rootfs, and anything recorded against the rootfs mtimes, such as the fontconfig caches, is wrong in it. Give mke2fs the rootfs mtime instead, as oe_mksquashfs does for mksquashfs. It is just as fixed, so the image stays reproducible. This changes the times stamped into an ext image. Every inode's atime, ctime, mtime and crtime, and the superblock's created, last write and last checked times, move from the image's SOURCE_DATE_EPOCH to REPRODUCIBLE_TIMESTAMP_ROOTFS. An image recipe has no source of its own, so its SOURCE_DATE_EPOCH is SOURCE_DATE_EPOCH_FALLBACK; with the bitbake.conf defaults for that and REPRODUCIBLE_TIMESTAMP_ROOTFS, the times move from 1302044400 (2011-04-05) to 1520598896 (2018-03-09). Where a distro sets REPRODUCIBLE_TIMESTAMP_ROOTFS earlier than SOURCE_DATE_EPOCH the inode times were not clamped and only the superblock times change. The directory hash seed is still derived from SOURCE_DATE_EPOCH and does not change. An ext image therefore differs from one built before this change. AI-Generated: Claude Opus 5.5 (Claude Code) Signed-off-by: Alex Kiernan --- meta/classes-recipe/image_types.bbclass | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/meta/classes-recipe/image_types.bbclass b/meta/classes-recipe/image_types.bbclass index c0b3a780131e..a5637c2226c8 100644 --- a/meta/classes-recipe/image_types.bbclass +++ b/meta/classes-recipe/image_types.bbclass @@ -92,6 +92,12 @@ oe_mkext234fs () { extra_imagecmd=$@ fi + # mke2fs reads SOURCE_DATE_EPOCH itself and clamps every inode time to it, + # so give it the time the rootfs files carry, as oe_mksquashfs does. + if [ -n "$SOURCE_DATE_EPOCH" ]; then + export SOURCE_DATE_EPOCH=$(stat -c '%Y' ${IMAGE_ROOTFS}) + fi + # For reproducible builds, make mke2fs/e2fsck deterministic: a fixed time and # directory hash seed (the fsck "-D" pass reorders directories using it). # This mirrors what wic does for its ext4 partitions. From patchwork Tue Oct 13 10:49:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Kiernan X-Patchwork-Id: 100594 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0641ACC6B03 for ; Tue, 13 Oct 2026 10:50:10 +0000 (UTC) Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4140.1791888600789002320 for ; Tue, 13 Oct 2026 03:50:01 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=R9pE0PPL; spf=pass (domain: gmail.com, ip: 209.85.128.43, mailfrom: alex.kiernan@gmail.com) Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-49ff680331aso23270945e9.3 for ; Tue, 13 Oct 2026 03:50:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791888599; x=1792493399; darn=lists.openembedded.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=L/j9iag7SFmf3Hfse0BIQHy0RfFliFSLuChwKvU/+NM=; b=R9pE0PPLU3pmwE+tlaIhondUnv6BI77Sl+H6hPbeseq/CJ+2zsQF4QwZOxwlROX9Wh E93xL7sFVpsTw68jbjQrkOyBU2o+4dt0uMLAeenN1RzzPPJmoZhBXmew1xnOnSHBTmf0 yrozC74hSC/EWXxyRcLsv734UG/7Vyzh7C7bWyQlO5uT/R6o2t1w1Ht2uV745Ccsdi4C biv1mn5u7HDSmGG1kyCqfdqToQ398Xa5LiV4j66HXbQxIBXhJYApBZ7UOo2gSA3UpuKP 1PgJRi8XKC5/H5ZoU2ZoE01FvbXkXnitJnZi8fo+G/NXYaJNSFTd/S+r+WxXHsKqvf7D 84JQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791888599; x=1792493399; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=L/j9iag7SFmf3Hfse0BIQHy0RfFliFSLuChwKvU/+NM=; b=DQsBXd4TXpZWe4bHrDgf0musqeLyUXLJ7XJ1FBjbn61EAYOscnBgb4jYEzqedBWcCP 2RF20/KY6vusvPpkOAipMZbjglJPahPPSAtauPi1c5TvHe7Ax7xEh81E7mTE6nLPs5Xm 5GWJqlmXq3v6lpZWjibZr4LSUxd1dRb4dELNorlBoGOdzhpnVbbN31wnwLCeueSAzVit 52FpXqSCCww1M/xukWoRK3RwzwrG6z291ab789IiJSNXHekt2/4GCgZbHpnTatuL+Oqe LmjKxMyI9jO0gedT1jwHP5SE+NtekDSAwGkeNBdDj0PXg/dWEdjEv8LtZVsg2SUih5iY fFbg== X-Gm-Message-State: AFq9FYKyxQSazr0ZJgyaud2/LgWKTZ7kNvROfOx/oWDFlwekwX+WLEz8 rGEHL9n6laMI5QEeS8Dk6MCaJWJ6Er2BpNgGeZXbp+bO+LfXyopiyLge1zuw3g== X-Gm-Gg: AYBFou1OTcmaaC8TH5xZePBVzQbkxloG3YKV4+HaSPXeI17C0SsmNytSzZzlNmxD9// gACQzhN4xaDa2SprgfyjCc8r6zF7Jg8rDhzR+US7YXhRCwVZTqI/2g55R1s2KNlIEwdYQyYhAq3 P/HP+Ye2dPRs2QThMFIPU5+vHUQAJUzADxU/Eyez+BOjy074xDIWSExX7FvotusEpeCpHtBa/ix z94duUVVpguQtj1pOWRAo5JvbTzJZDSFtAboN92eVrbnaXSyskcelspSEAhagRXQBAPLFG831fT vuA3RpEJe521mNob1T+8eQiMmNLcMH/jeOr5u+qi2wSJpJJD/Rg9bkoXePZ2jh2NDqMiw3ySOQq 5ANoNiUdkyF+oHnq9zWPepz7HEOhI3X1nOUx27/Ej1jqTSGbBq9DOxSaHHIBETVyN8mWM0sYXs4 I7hf3xAEYUG86y333XlHpUat150aW+hM9x+b4S+fm5fGAQfMboRJ6+TsliaQA2LwREt83VP0bx8 BB1BsVHGnqb2K99Rg63NluD8YBPcRW2Wlcy44aOJpuDw9Hvxw== X-Received: by 2002:a05:600c:46d1:b0:4a1:7d56:663b with SMTP id 5b1f17b1804b1-4a18e4a7844mr256455185e9.24.1791888598864; Tue, 13 Oct 2026 03:49:58 -0700 (PDT) Received: from [192.168.5.15] (cust18-dsl93-89-130.idnet.net. [93.89.130.18]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a19303d4a9sm31623155e9.2.2026.10.13.03.49.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Oct 2026 03:49:55 -0700 (PDT) From: Alex Kiernan Date: Tue, 13 Oct 2026 11:49:38 +0100 Subject: [PATCH 4/4] oeqa/selftest: check the font caches an image ships are used MIME-Version: 1.0 Message-Id: <20261013-fontcache-reproducible-mtime-v1-4-950f07b80f0f@gmail.com> References: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> In-Reply-To: <20261013-fontcache-reproducible-mtime-v1-0-950f07b80f0f@gmail.com> To: openembedded-core@lists.openembedded.org Cc: Alex Kiernan X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 13 Oct 2026 10:50:10 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/247720 Boot an image carrying a font and have fontconfig report the caches it checks: every one must match its directory, and nothing may be written, neither to the system cache nor to a per-user one. AI-Generated: Claude Opus 5.5 (Claude Code) Signed-off-by: Alex Kiernan --- meta/lib/oeqa/selftest/cases/fontcache.py | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/fontcache.py b/meta/lib/oeqa/selftest/cases/fontcache.py new file mode 100644 index 000000000000..df88a229aab2 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/fontcache.py @@ -0,0 +1,42 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import re + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.core.decorator import OETestTag +from oeqa.utils.commands import bitbake, runqemu + +class FontCache(OESelftestTestCase): + + @OETestTag("runqemu") + def test_image_font_cache_is_valid(self): + """ + Summary: Check the fontconfig caches built into an image are used + Expected: fontconfig accepts the cache of every font directory and + writes no cache of its own, system or per-user + Product: oe-core + """ + features = 'EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"\n' + features += 'IMAGE_INSTALL:append = " ttf-bitstream-vera"\n' + self.write_config(features) + bitbake('core-image-minimal') + + with runqemu('core-image-minimal') as qemu: + # FC_DEBUG=16 reports each cache fontconfig checks and each one it + # writes. An empty HOME catches a per-user cache, which fontconfig + # writes whenever it cannot use the system one. + status, output = qemu.run_serial( + 'H=$(mktemp -d); HOME=$H XDG_CACHE_HOME=$H FC_DEBUG=16 fc-match sans-serif; echo "user cache: [$(ls -A $H)]"') + self.assertEqual(status, 1, msg=output) + + checks = re.findall(r'FcCacheTimeValid dir "([^"]+)" cache checksum (\d+) dir checksum (\d+)', output) + self.assertTrue(checks, msg="fontconfig checked no cache:\n" + output) + for directory, cache, mtime in checks: + self.assertEqual(cache, mtime, msg="%s: the cache records mtime %s, the directory has %s\n%s" % (directory, cache, mtime, output)) + + self.assertNotIn('FcDirCacheWriteDir', output, msg="fontconfig rewrote a cache:\n" + output) + self.assertIn('user cache: []', output, msg="fontconfig wrote a per-user cache:\n" + output)