Skip to content

Commit

Permalink
overlayfs-setup: Fallback to read only mount when overlay not supported
Browse files Browse the repository at this point in the history
Overlayfs doesn't support using case insensitive filesystems such as
vfat and exfat as a lower directory. Change the mount to read only so
changes can't be made there.

In theory this would simply be `mount -o remount,ro`. Unfortunately,
if systemd has setup an automount, autofs is not our friend. In that
case, the mount options need to be persisted into the mount unit so that
a subsequent remounting retains the ro option.

https://phabricator.endlessm.com/T35641
  • Loading branch information
dbnicholson committed Oct 16, 2024
1 parent 494fb99 commit 8bd6208
Showing 1 changed file with 66 additions and 1 deletion.
67 changes: 66 additions & 1 deletion eos-live-boot-overlayfs-setup
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,64 @@ setup_and_mount_storage() {
mount "${device}" /run/eos-live
}

setup_ro_mount() {
local path=$1

# If the directory isn't a mount point, make a read only bind mount
# on top of the directory and be done.
if ! findmnt "$path" >/dev/null; then
mount -o bind,ro "$path" "$path"
return 0
fi

# In case of an automount, trigger the real mount so its options can
# be inspected.
ls "$path" >/dev/null

# If it's already mounted read only, assume we're done.
local mounted_options
mounted_options=$(findmnt -n -f -d backward -o OPTIONS "$path")
[[ $mounted_options =~ (,|^)ro(,|$) ]] && return 0

# If there's an automount, adjust the mount options in the mount
# unit so the read only option persists across mountings.
local escaped_path automount_unit
escaped_path=$(systemd-escape -p "$path")
automount_unit="${escaped_path}.automount"
if systemctl -q is-active "$automount_unit"; then
# If the mount unit's Options don't contain ro, add a drop-in to
# set it.
local mount_unit mount_options new_mount_options
mount_unit="${escaped_path}.mount"
mount_options=$(systemctl show -P Options "$mount_unit")
if [[ $mount_options =~ (,|^)(ro|rw)(,|$) ]]; then
new_mount_options=$(sed -E 's/(,|^)rw(,|$)/\1ro\2/' <<< "$mount_options")
else
new_mount_options="${mount_options}${mount_options:+,}ro"
fi

if [ "$new_mount_options" != "$mount_options" ]; then
local dropin_dir="/run/systemd/system/${mount_unit}.d"
local dropin_conf="${dropin_dir}/readonly.conf"
mkdir -p "$dropin_dir"
echo "Changing ${mount_unit} Options from \"${mount_options}\"" \
"to \"${new_mount_options}\"" >&2
cat > "$dropin_conf" <<EOF
[Mount]
Options=${new_mount_options}
EOF
systemctl daemon-reload
fi

# Make sure the mount unit is started so the subsequent
# remount isn't applied to the automount.
systemctl start "$mount_unit"
fi

# Remount the current mount read only.
mount -o remount,ro "$path"
}

setup_overlay() {
local dir=$1
[ -d "/$dir" ] || return
Expand All @@ -99,9 +157,16 @@ setup_overlay() {
# multiple times.
findmnt -t overlay "/$dir" >/dev/null && return 0
mkdir -p "/run/eos-live/$dir" "/run/eos-live/$dir-workdir"
mount -t overlay -o \
if ! mount -t overlay -o \
"rw,upperdir=/run/eos-live/$dir,lowerdir=/$dir,workdir=/run/eos-live/$dir-workdir" \
"eos-live-$dir" "/$dir"
then
# Overlayfs doesn't support using case insensitive filesystems
# such as vfat and exfat as a lower directory. Change the mount
# to read only so changes can't be made there.
echo "Could not mount overlayfs on /$dir, trying to mount read only" >&2
setup_ro_mount "/$dir"
fi
}

# Use persistent storage to back overlayfses, if available
Expand Down

0 comments on commit 8bd6208

Please sign in to comment.