lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 2c31fee 09/10: Destroy chroots more carefully


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 2c31fee 09/10: Destroy chroots more carefully
Date: Fri, 26 Jun 2020 08:05:20 -0400 (EDT)

branch: master
commit 2c31feea398d0a4947fe01e4f8f22ce64208c607
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Destroy chroots more carefully
    
    Explicitly test the two critical postconditions:
     - the chroot's bind mounts have been unmounted
     - the directory where the chroot resided no longer exists
    in that order; exit early, with a diagnostic, unless both are true.
    Downstream, assert again that the directory where a new chroot is to
    reside does not yet exist.
    
    The need for such strictness is demonstrated by two recent mishaps:
    
     - A chroot had a bind mount that wasn't explicitly listed, so it
       wasn't umounted. Then the 'rm -rf' command intended to remove the
       directory where it resided removed the host system's '/run',
       necessitating a reboot.
    
     - The directory where a chroot resided wasn't destroyed, because
       its '.conf' file had already been removed (probably as a result
       of the first mishap), so
         $(schroot --chroot=centos7lmi --location)
       returned an empty string, and calling 'rm -rf' with that empty
       string as an argument did nothing, silently. Then running
       'debootstrap' to recreate it didn't work as hoped: its output
       was all "I" (informational) messages, culminating in the
       unexpected
         I: Chosen extractor for .deb packages: dpkg-deb
       but it returned an exit code of "1" (failure), which was eaten
       by a pipeline that "succeeded". The "Chosen extractor" message
       was a false lead that pointed down a proverbial rabbit hole.
---
 lmi_setup_00c.sh |  1 +
 lmi_setup_02.sh  | 30 ++++++++++++++++++++++++------
 lmi_setup_02c.sh | 18 ++++++++++++++++--
 lmi_setup_11.sh  | 12 +++++++++++-
 4 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/lmi_setup_00c.sh b/lmi_setup_00c.sh
index b424350..b39bc02 100755
--- a/lmi_setup_00c.sh
+++ b/lmi_setup_00c.sh
@@ -68,6 +68,7 @@ touch    /etc/schroot/lmi_profile/nssdatabases
 CACHEDIR=/var/cache/lmi_schroots
 mkdir -p "${CACHEDIR}"
 
+if [ -e /srv/chroot/centos7lmi ] ; then echo "Oops."; exit 9; fi
 rinse --arch amd64 --distribution centos-7 \
   --cache-dir "${CACHEDIR}" \
   --directory /srv/chroot/centos7lmi \
diff --git a/lmi_setup_02.sh b/lmi_setup_02.sh
index f81439a..4e1691c 100755
--- a/lmi_setup_02.sh
+++ b/lmi_setup_02.sh
@@ -79,21 +79,39 @@ findmnt -ro SOURCE,TARGET \
   | sed -e's,^[/A-Za-z0-9_-]*[[]\([^]]*\)[]],\1,' \
   | column -t
 
+# Abort if any $CHRTNAME mountpoint remains.
+#
+# This shouldn't occur, and 'rm --one-file-system' below should be
+# safe anyway, yet an actual catastrophe did occur nonetheless.
+findmnt | grep "${CHRTNAME}" && exit 9
+
 # Use '--one-file-system' because it was designed for this use case:
 #   https://lists.gnu.org/archive/html/bug-coreutils/2006-10/msg00332.html
 # | This option is useful when removing a build "chroot" hierarchy
 #
-# Use 'schroot --location' rather than /srv/chroot/"$CHRTNAME" because
-# chroots need not be located in /srv .
+# These scripts create a chroot in /srv/chroot/"$CHRTNAME", but
+# chroots need not be located in /srv , so use 'schroot --location'
+# to attempt to detect any manual override. Such detection may fail
+# (e.g., if the chroot's '.conf' file is missing).
+
+loc0=/srv/chroot/"${CHRTNAME}"
+loc1="$(schroot --chroot="${CHRTNAME}" --location)"
+if [ -n "${loc1}" ] && [ "${loc0}" != "${loc1}" ]; then
+  echo "chroot found in unexpected location--remove it manually"
+  exit 9
+fi
 
-rm --one-file-system --recursive --force \
-  "$(schroot --chroot="${CHRTNAME}" --location)"
+# Remove the directory that these scripts would create. Removing
+# "${loc1}" wouldn't be appropriate because it can be an empty string.
+
+rm --one-file-system --recursive --force "${loc0}"
+
+# Explicitly test postcondition.
+if [ -e "${loc0}" ] || [ -e "${loc1}" ] ; then echo "Oops."; exit 9; fi
 
 # schroot allows configuration files in /etc/schroot/chroot.d/ only.
 
 rm --force /etc/schroot/chroot.d/"${CHRTNAME}".conf
 
-# These commands fail harmlessly if the chroot doesn't already exist.
-
 stamp=$(date -u +'%Y%m%dT%H%M%SZ')
 echo "$stamp $0: Removed old chroot."  | tee /dev/tty
diff --git a/lmi_setup_02c.sh b/lmi_setup_02c.sh
index e3a890c..3f77bfa 100755
--- a/lmi_setup_02c.sh
+++ b/lmi_setup_02c.sh
@@ -44,8 +44,22 @@ findmnt -ro SOURCE,TARGET \
   | sed -e's,^[/A-Za-z0-9_-]*[[]\([^]]*\)[]],\1,' \
   | column -t
 
-rm --one-file-system --recursive --force \
-  "$(schroot --chroot=centos7lmi --location)"
+# Abort if any centos lmi mountpoint remains.
+#
+# This shouldn't occur, and 'rm --one-file-system' below should be
+# safe anyway, yet an actual catastrophe did occur nonetheless.
+findmnt | grep 'centos.*lmi' && exit 9
+
+loc0=/srv/chroot/centos7lmi
+loc1="$(schroot --chroot=centos7lmi --location)"
+if [ -n "${loc1}" ] && [ "${loc0}" != "${loc1}" ]; then
+  echo "chroot found in unexpected location--remove it manually"
+  exit 9
+fi
+
+rm --one-file-system --recursive --force "${loc0}"
+if [ -e "${loc0}" ] || [ -e "${loc1}" ] ; then echo "Oops."; exit 9; fi
+
 rm --force /etc/schroot/chroot.d/centos7lmi.conf
 
 stamp=$(date -u +'%Y%m%dT%H%M%SZ')
diff --git a/lmi_setup_11.sh b/lmi_setup_11.sh
index 906c314..5f008da 100755
--- a/lmi_setup_11.sh
+++ b/lmi_setup_11.sh
@@ -47,11 +47,21 @@ assert_not_chrooted
 CACHEDIR=/var/cache/lmi_schroots
 mkdir -p "${CACHEDIR}"
 
+# At this point,
+#   /srv/
+# probably exists already; and
+#   /srv/chroot/
+# might not exist (in which case 'debootstrap' will create it); but
+#   /srv/chroot/"${CHRTNAME}"
+# should not exist--debootstrapping into a nonempty directory can
+# fail in mysterious ways.
+if [ -e /srv/chroot/"${CHRTNAME}" ] ; then echo "Oops."; exit 9; fi
+mkdir -p /srv/chroot/"${CHRTNAME}"
+
 # Bootstrap a minimal debian system. Options:
 #   --include=zsh, because of "shell=/bin/zsh" below
 #   --variant=minbase, as explained here:
 #     https://lists.nongnu.org/archive/html/lmi/2020-05/msg00026.html
-mkdir -p /srv/chroot/"${CHRTNAME}"
 debootstrap --arch=amd64 --cache-dir="${CACHEDIR}" \
  --variant=minbase --include=zsh \
  "${CODENAME}" /srv/chroot/"${CHRTNAME}" >"${CHRTNAME}"-debootstrap-log 2>&1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]