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