]> git.ipfire.org Git - thirdparty/dracut-ng.git/commitdiff
fix(dracut): ensure hardlink deduplication is reproducible
authorChris Riches <chris.riches@nutanix.com>
Wed, 9 Jul 2025 16:40:18 +0000 (16:40 +0000)
committerLaszlo <laszlo.gombos@gmail.com>
Tue, 15 Jul 2025 13:48:47 +0000 (09:48 -0400)
By default, hardlink will only deduplicate files with identical mtimes,
down to one-second granularity. If a dracut module rapidly generates
multiple identical files, it is completely up to chance as to whether
their mtimes cross a second boundary or not, and thus whether they get
deduplicated or not. This results in non-reproducible output.

Re-order hardlink with respect to clamping to avoid this problem.

Fixes: https://issues.redhat.com/browse/RHEL-101901
dracut.sh

index 9209bd1731d3a8085fd0eee6fd413b40dd00fca8..387b880febee90bd774ab735a77b319c74a339c4 100755 (executable)
--- a/dracut.sh
+++ b/dracut.sh
@@ -2259,12 +2259,6 @@ for ((i = 0; i < ${#include_src[@]}; i++)); do
     fi
 done
 
-if [[ $do_hardlink == yes ]] && command -v hardlink > /dev/null; then
-    dinfo "*** Hardlinking files ***"
-    hardlink "$initdir" 2>&1 | ddebug
-    dinfo "*** Hardlinking files done ***"
-fi
-
 # strip binaries
 if [[ $do_strip == yes ]]; then
     # Prefer strip from elfutils for package size
@@ -2461,7 +2455,7 @@ if [[ $uefi == yes ]]; then
 fi
 
 clamp_mtimes() {
-    find "$1" -newer "$dracutbasedir/dracut-functions.sh" -print0 \
+    find "$@" -newer "$dracutbasedir/dracut-functions.sh" -print0 \
         | xargs -r -0 touch -h -m -c -r "$dracutbasedir/dracut-functions.sh"
 }
 
@@ -2475,6 +2469,19 @@ if [[ $DRACUT_REPRODUCIBLE ]]; then
     fi
 fi
 
+# Hardlink is mtime-sensitive; do it after the above clamp.
+if [[ $do_hardlink == yes ]] && command -v hardlink > /dev/null; then
+    dinfo "*** Hardlinking files ***"
+    hardlink "$initdir" 2>&1 | ddebug
+    dinfo "*** Hardlinking files done ***"
+
+    # Hardlink itself breaks mtimes on directories as we may have added/removed
+    # dir entries. Fix those up.
+    if [[ $DRACUT_REPRODUCIBLE ]]; then
+        clamp_mtimes "$initdir" -type d
+    fi
+fi
+
 [[ $EUID != 0 ]] && cpio_owner="0:0"
 
 if [[ $create_early_cpio == yes ]]; then