9f65cc
From 5e4bc6e2d6b6829c45f4e25cce4d81661b798587 Mon Sep 17 00:00:00 2001
9f65cc
From: Lukas Nykryn <lnykryn@redhat.com>
9f65cc
Date: Thu, 29 Jul 2021 15:16:39 +0200
9f65cc
Subject: [PATCH] refactor(squash): structure in a cleaner way
9f65cc
9f65cc
Simplify the squash mount layout. Instead of overlay on each top
9f65cc
directory (/etc, /usr), just mount and switch_root into the squash
9f65cc
image, with a overlay on top of it.
9f65cc
9f65cc
Also install the binaries and setup scripts separately, so the squash
9f65cc
setup code and the squash image content is independent of each other,
9f65cc
all squash setup script and binaries can be deleted safely upon
9f65cc
switch_root.
9f65cc
9f65cc
With this change, previous squash clean up service and other tricky
9f65cc
implementations are all gone.
9f65cc
9f65cc
This commit depends on systemd commits from:
9f65cc
https://github.com/systemd/systemd/pull/18124
9f65cc
9f65cc
Previouly systemd doesn't recognize non-ramfs initramfs, now this is
9f65cc
doable with SYSTEMD_IN_INITRD=lenient
9f65cc
9f65cc
Signed-off-by: Kairui Song <kasong@redhat.com>
9f65cc
(cherry picked from commit 8f7c332e488f88e5845a3c7954af7934c2f1e37b)
9f65cc
9f65cc
Cherry-picked from: 8f7c332e
9f65cc
Resolves: #1959336
9f65cc
---
9f65cc
 dracut-initramfs-restore.sh                 |  4 +-
9f65cc
 dracut.sh                                   |  4 +-
9f65cc
 lsinitrd.sh                                 |  6 +--
9f65cc
 modules.d/99squash/clear-squash.sh          |  6 ---
9f65cc
 modules.d/99squash/init-squash.sh           | 70 ++++++++---------------------
9f65cc
 modules.d/99squash/module-setup.sh          | 56 ++++++++---------------
9f65cc
 modules.d/99squash/squash-mnt-clear.service | 17 -------
9f65cc
 7 files changed, 44 insertions(+), 119 deletions(-)
9f65cc
9f65cc
diff --git a/dracut-initramfs-restore.sh b/dracut-initramfs-restore.sh
9f65cc
index 67fc88fa..74a952c4 100644
9f65cc
--- a/dracut-initramfs-restore.sh
9f65cc
+++ b/dracut-initramfs-restore.sh
9f65cc
@@ -41,9 +41,9 @@ else
9f65cc
 fi
9f65cc
 
9f65cc
 if [[ -d squash ]]; then
9f65cc
-    unsquashfs -no-xattrs -f -d . squash/root.img >/dev/null
9f65cc
+    unsquashfs -no-xattrs -f -d . squash-root.img >/dev/null
9f65cc
     if [ $? -ne 0 ]; then
9f65cc
-        echo "Squash module is enabled for this initramfs but failed to unpack squash/root.img" >&2
9f65cc
+        echo "Squash module is enabled for this initramfs but failed to unpack squash-root.img" >&2
9f65cc
         rm -f -- /run/initramfs/shutdown
9f65cc
         exit 1
9f65cc
     fi
9f65cc
diff --git a/dracut.sh b/dracut.sh
9f65cc
index 1168fc16..b403f401 100755
9f65cc
--- a/dracut.sh
9f65cc
+++ b/dracut.sh
9f65cc
@@ -1758,8 +1758,8 @@ fi
9f65cc
 
9f65cc
 if dracut_module_included "squash"; then
9f65cc
     readonly squash_dir="$initdir/squash/root"
9f65cc
-    readonly squash_img="$initdir/squash/root.img"
9f65cc
-
9f65cc
+    readonly squash_img="$initdir/squash-root.img"
9f65cc
+    mkdir -p "$squash_dir"
9f65cc
     dinfo "*** Install squash loader ***"
9f65cc
     DRACUT_SQUASH_POST_INST=1 module_install "squash"
9f65cc
 fi
9f65cc
diff --git a/lsinitrd.sh b/lsinitrd.sh
9f65cc
index 0b42b9a4..04ce9e8b 100755
9f65cc
--- a/lsinitrd.sh
9f65cc
+++ b/lsinitrd.sh
9f65cc
@@ -162,9 +162,9 @@ list_files()
9f65cc
 
9f65cc
 list_squash_content()
9f65cc
 {
9f65cc
-    SQUASH_IMG="squash/root.img"
9f65cc
-    SQUASH_TMPFILE="$(mktemp -t --suffix=.root.sqsh lsinitrd.XXXXXX)"
9f65cc
-    trap "rm -f '$SQUASH_TMPFILE'" EXIT
9f65cc
+    SQUASH_IMG="squash-root.img"
9f65cc
+    SQUASH_TMPFILE="$TMPDIR/initrd.root.sqsh"
9f65cc
+
9f65cc
     $CAT "$image" 2>/dev/null | cpio --extract --verbose --quiet --to-stdout -- \
9f65cc
         $SQUASH_IMG > "$SQUASH_TMPFILE" 2>/dev/null
9f65cc
     if [[ -s $SQUASH_TMPFILE ]]; then
9f65cc
diff --git a/modules.d/99squash/clear-squash.sh b/modules.d/99squash/clear-squash.sh
9f65cc
deleted file mode 100755
9f65cc
index 4f357817..00000000
9f65cc
--- a/modules.d/99squash/clear-squash.sh
9f65cc
+++ /dev/null
9f65cc
@@ -1,6 +0,0 @@
9f65cc
-#!/bin/bash
9f65cc
-mnt="/squash/root"
9f65cc
-for dir in jsquash/root/*; do
9f65cc
-	mnt="$mnt ${dir#$SQUASH_MNT}"
9f65cc
-done
9f65cc
-umount --lazy -- $mnt
9f65cc
diff --git a/modules.d/99squash/init-squash.sh b/modules.d/99squash/init-squash.sh
9f65cc
index fee0105e..3de6f819 100755
9f65cc
--- a/modules.d/99squash/init-squash.sh
9f65cc
+++ b/modules.d/99squash/init-squash.sh
9f65cc
@@ -1,61 +1,29 @@
9f65cc
-#!/bin/bash
9f65cc
+#!/bin/sh
9f65cc
 PATH=/bin:/sbin
9f65cc
 
9f65cc
-SQUASH_IMG=/squash/root.img
9f65cc
-SQUASH_MNT=/squash/root
9f65cc
+# Basic mounts for mounting a squash image
9f65cc
+mkdir /proc /sys /dev /run
9f65cc
+mount -t proc -o nosuid,noexec,nodev proc /proc
9f65cc
+mount -t sysfs -o nosuid,noexec,nodev sysfs /sys
9f65cc
+mount -t devtmpfs -o mode=755,noexec,nosuid,strictatime devtmpfs /dev
9f65cc
+mount -t tmpfs -o mode=755,nodev,nosuid,strictatime tmpfs /run
9f65cc
 
9f65cc
-# Following mount points are neccessary for mounting a squash image
9f65cc
-
9f65cc
-[ ! -d /proc/self ] && \
9f65cc
-    mount -t proc -o nosuid,noexec,nodev proc /proc
9f65cc
-
9f65cc
-[ ! -d /sys/kernel ] && \
9f65cc
-    mount -t sysfs -o nosuid,noexec,nodev sysfs /sys
9f65cc
-
9f65cc
-[ ! -e /dev/loop-control ] && \
9f65cc
-    mount -t devtmpfs -o mode=0755,noexec,nosuid,strictatime devtmpfs /dev
9f65cc
-
9f65cc
-# Need a loop device backend, overlayfs, and squashfs module
9f65cc
+# Load required modules
9f65cc
 modprobe loop
9f65cc
-if [ $? != 0 ]; then
9f65cc
-    echo "Unable to setup loop module"
9f65cc
-fi
9f65cc
-
9f65cc
 modprobe squashfs
9f65cc
-if [ $? != 0 ]; then
9f65cc
-    echo "Unable to setup squashfs module"
9f65cc
-fi
9f65cc
-
9f65cc
 modprobe overlay
9f65cc
-if [ $? != 0 ]; then
9f65cc
-    echo "Unable to setup overlay module"
9f65cc
-fi
9f65cc
-
9f65cc
-[ ! -d "$SQUASH_MNT" ] && \
9f65cc
-	mkdir -m 0755 -p $SQUASH_MNT
9f65cc
-
9f65cc
-# Mount the squashfs image
9f65cc
-mount -t squashfs -o ro,loop $SQUASH_IMG $SQUASH_MNT
9f65cc
-
9f65cc
-if [ $? != 0 ]; then
9f65cc
-    echo "Unable to mount squashed initramfs image"
9f65cc
-fi
9f65cc
-
9f65cc
-for file in $SQUASH_MNT/*; do
9f65cc
-	file=${file#$SQUASH_MNT/}
9f65cc
-	lowerdir=$SQUASH_MNT/$file
9f65cc
-	workdir=/squash/overlay-work/$file
9f65cc
-	upperdir=/$file
9f65cc
-	mntdir=/$file
9f65cc
 
9f65cc
-	mkdir -m 0755 -p $workdir
9f65cc
-	mkdir -m 0755 -p $mntdir
9f65cc
+# Mount the squash image
9f65cc
+mount -t ramfs ramfs /squash
9f65cc
+mkdir -p /squash/root /squash/overlay/upper /squash/overlay/work
9f65cc
+mount -t squashfs -o ro,loop /squash-root.img /squash/root
9f65cc
 
9f65cc
-	mount -t overlay overlay -o\
9f65cc
-		lowerdir=$lowerdir,upperdir=$upperdir,workdir=$workdir $mntdir
9f65cc
-done
9f65cc
+# Setup new root overlay
9f65cc
+mkdir /newroot
9f65cc
+mount -t overlay overlay -o lowerdir=/squash/root,upperdir=/squash/overlay/upper,workdir=/squash/overlay/work/ /newroot/
9f65cc
 
9f65cc
-exec /init.orig
9f65cc
+# Move all mount points to new root to prepare chroot
9f65cc
+mount --move /squash /newroot/squash
9f65cc
 
9f65cc
-echo "Something went wrong when trying to exec original init!"
9f65cc
-exit 1
9f65cc
+# Jump to new root and clean setup files
9f65cc
+SYSTEMD_IN_INITRD=lenient exec switch_root /newroot /init
9f65cc
diff --git a/modules.d/99squash/module-setup.sh b/modules.d/99squash/module-setup.sh
9f65cc
index ad619176..50c92c31 100644
9f65cc
--- a/modules.d/99squash/module-setup.sh
9f65cc
+++ b/modules.d/99squash/module-setup.sh
9f65cc
@@ -19,56 +19,36 @@ depends() {
9f65cc
 }
9f65cc
 
9f65cc
 installpost() {
9f65cc
-    local squash_candidate=( "usr" "etc" )
9f65cc
-
9f65cc
-    # shellcheck disable=SC2174
9f65cc
-    mkdir -m 0755 -p "$squash_dir"
9f65cc
-    for folder in "${squash_candidate[@]}"; do
9f65cc
-        mv "$initdir/$folder" "$squash_dir/$folder"
9f65cc
+    # Move everything under $initdir except $squash_dir
9f65cc
+    # itself into squash image
9f65cc
+    for i in "$initdir"/*; do
9f65cc
+        [[ "$squash_dir" == "$i"/* ]] || mv "$i" "$squash_dir"/
9f65cc
     done
9f65cc
 
9f65cc
-    # Move some files out side of the squash image, including:
9f65cc
-    # - Files required to boot and mount the squashfs image
9f65cc
-    # - Files need to be accessible without mounting the squash image
9f65cc
-    # - Initramfs marker
9f65cc
-    for file in \
9f65cc
-        "$squash_dir"/usr/lib/dracut/* \
9f65cc
-        "$squash_dir"/etc/initrd-release
9f65cc
-    do
9f65cc
+    # Create mount points for squash loader
9f65cc
+    mkdir -p "$initdir"/squash/
9f65cc
+    mkdir -p "$squash_dir"/squash/
9f65cc
+
9f65cc
+    # Copy dracut spec files out side of the squash image
9f65cc
+    # so dracut rebuild and lsinitrd can work
9f65cc
+    for file in "$squash_dir"/usr/lib/dracut/*; do
9f65cc
         [[ -f $file ]] || continue
9f65cc
         DRACUT_RESOLVE_DEPS=1 dracutsysrootdir="$squash_dir" inst "${file#$squash_dir}"
9f65cc
-        rm "$file"
9f65cc
-    done
9f65cc
-
9f65cc
-    # Install required files for the squash image setup script.
9f65cc
-    inst_multiple modprobe mount mkdir ln echo rm
9f65cc
-
9f65cc
-    mv "$initdir"/init "$initdir"/init.orig
9f65cc
-    inst "$moddir"/init-squash.sh /init
9f65cc
-    inst "$moddir"/clear-squash.sh /squash/clear-squash.sh
9f65cc
-
9f65cc
-    # Keep systemctl outsite if we need switch root
9f65cc
-    if [[ ! -f "$initdir/lib/dracut/no-switch-root" ]]; then
9f65cc
-      inst "systemctl"
9f65cc
-    fi
9f65cc
-
9f65cc
-    # Remove duplicated files
9f65cc
-    for folder in "${squash_candidate[@]}"; do
9f65cc
-        find "$initdir/$folder/" -not -type d \
9f65cc
-            -exec bash -c 'mv -f "$squash_dir${1#$initdir}" "$1"' -- "{}" \;
9f65cc
     done
9f65cc
 
9f65cc
-    # Install required modules for the squash image init script.
9f65cc
+    # Install required modules and binaries for the squash image init script.
9f65cc
+    DRACUT_RESOLVE_DEPS=1 inst_multiple sh mount modprobe mkdir switch_root
9f65cc
     hostonly="" instmods "loop" "squashfs" "overlay"
9f65cc
     dracut_kernel_post
9f65cc
+
9f65cc
+    # Install squash image init script.
9f65cc
+    ln -sfn /usr/bin "$initdir/bin"
9f65cc
+    ln -sfn /usr/sbin "$initdir/sbin"
9f65cc
+    inst_simple "$moddir"/init-squash.sh /init
9f65cc
 }
9f65cc
 
9f65cc
 install() {
9f65cc
     if [[ $DRACUT_SQUASH_POST_INST ]]; then
9f65cc
         installpost
9f65cc
-        return
9f65cc
     fi
9f65cc
-
9f65cc
-    inst "$moddir/squash-mnt-clear.service" "$systemdsystemunitdir/squash-mnt-clear.service"
9f65cc
-    systemctl -q --root "$initdir" add-wants initrd-switch-root.target squash-mnt-clear.service
9f65cc
 }
9f65cc
diff --git a/modules.d/99squash/squash-mnt-clear.service b/modules.d/99squash/squash-mnt-clear.service
9f65cc
deleted file mode 100644
9f65cc
index 84441f60..00000000
9f65cc
--- a/modules.d/99squash/squash-mnt-clear.service
9f65cc
+++ /dev/null
9f65cc
@@ -1,17 +0,0 @@
9f65cc
-#  This file is part of dracut.
9f65cc
-#
9f65cc
-
9f65cc
-[Unit]
9f65cc
-Description=Cleanup squashfs mounts when switch root
9f65cc
-DefaultDependencies=no
9f65cc
-Before=initrd-switch-root.service
9f65cc
-After=initrd-switch-root.target
9f65cc
-ConditionPathExists=/squash/root
9f65cc
-
9f65cc
-[Service]
9f65cc
-Type=oneshot
9f65cc
-RemainAfterExit=no
9f65cc
-StandardInput=null
9f65cc
-StandardOutput=syslog+console
9f65cc
-StandardError=syslog+console
9f65cc
-ExecStart=/squash/clear-squash.sh
9f65cc