Skip to content

Commit

Permalink
alpine: avoid wiping out writable host mounts under /home, etc.
Browse files Browse the repository at this point in the history
A host directory could be wiped out when all the following conditions are met:
- The directory is mounted to Lima via virtiofs, or, potentially 9p
- The mount is writable
- The mount point in the guest is under one of: /etc /home /root /usr/local /var/lib
- The guest OS is Alpine Linux

Fix issue 2221
Fix rancher-sandbox/rancher-desktop issue 6582

Co-authored-by: Jan Dubois <[email protected]>
Signed-off-by: Akihiro Suda <[email protected]>
  • Loading branch information
AkihiroSuda and jandubois committed Mar 9, 2024
1 parent b1dbefb commit 65f247d
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions pkg/cidata/cidata.TEMPLATE.d/boot/04-persistent-data-volume.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,42 @@ if [ "$(awk '$2 == "/" {print $3}' /proc/mounts)" == "tmpfs" ]; then
PART=$(lsblk --list /dev/"${DISK}" --noheadings --output name,type | awk '$2 == "part" {print $1}')
mkfs.ext4 -L data-volume /dev/"${PART}"
mount -t ext4 /dev/disk/by-label/data-volume /mnt/data
# Unmount all mount points under /tmp so we can move it to the data volume:
# "mount1 on /tmp/lima type 9p (rw,dirsync,relatime,mmap,access=client,trans=virtio)"
for MP in $(mount | awk '$3 ~ /^\/tmp\// {print $3}'); do
umount "${MP}"
done
# setup apk package cache
mkdir -p /mnt/data/apk/cache
mkdir -p /etc/apk
ln -s /mnt/data/apk/cache /etc/apk/cache
# Prepare mnt.sh (used for restoring mounts later)
echo "#!/bin/sh" >/mnt/data/mnt.sh
echo "set -eux" >>/mnt/data/mnt.sh
# Move all persisted directories to the data volume
for DIR in ${DATADIRS}; do
DEST="/mnt/data$(dirname "${DIR}")"
mkdir -p "${DIR}" "${DEST}"
while IFS= read -r LINE; do
[ -z "$LINE" ] && continue
MNTDEV="$(echo "${LINE}" | awk '{print $1}')"
# unmangle " \t\n\\#"
# https://github.com/torvalds/linux/blob/v6.6/fs/proc_namespace.c#L89
MNTPNT="$(echo "${LINE}" | awk '{print $2}' | sed -e 's/\\040/ /g; s/\\011/\t/g; s/\\012/\n/g; s/\\134/\\/g; s/\\043/#/g')"
# Ignore if MNTPNT is neither DIR nor a parent directory of DIR.
# It is not a parent if MNTPNT doesn't start with DIR, or the first
# character after DIR isn't a slash.
# shellcheck disable=SC2295
WITHOUT_DIR=${MNTPNT#$DIR}
# shellcheck disable=SC2166
[ "$MNTPNT" != "$DIR" ] && [ "$MNTPNT" == "$WITHOUT_DIR" -o "${WITHOUT_DIR::1}" != "/" ] && continue
MNTTYPE="$(echo "${LINE}" | awk '{print $3}')"
[ "${MNTTYPE}" = "ext4" ] && continue
[ "${MNTTYPE}" = "tmpfs" ] && continue
MNTOPTS="$(echo "${LINE}" | awk '{print $4}')"
echo "mount -t ${MNTTYPE} -o ${MNTOPTS} ${MNTDEV} ${MNTPNT}" >>/mnt/data/mnt.sh
# Before mv, unmount filesystems (virtiofs, 9p, etc.) below "${DIR}", otherwise host mounts will be wiped out
# https://github.com/rancher-sandbox/rancher-desktop/issues/6582
umount "${MNTPNT}" || exit 1
done </proc/mounts
mv "${DIR}" "${DEST}"
done
chmod +x /mnt/data/mnt.sh
# Make sure all data moved to the persistent volume has been committed to disk
sync
break
Expand All @@ -88,8 +109,8 @@ if [ "$(awk '$2 == "/" {print $3}' /proc/mounts)" == "tmpfs" ]; then
mount --bind /mnt/data"${DIR}" "${DIR}"
fi
done
# Make sure to re-mount any mount points under /tmp
mount -a
# Remount submounts on top of the new ${DIR}
/mnt/data/mnt.sh
# Reinstall packages from /mnt/data/apk/cache into the RAM disk
apk fix --no-network
fi

0 comments on commit 65f247d

Please sign in to comment.