Skip to content

Commit

Permalink
Make 98selinux-microos usable on non-transactional systems
Browse files Browse the repository at this point in the history
Detect whether / is btrfs and /etc is an overlay mount and take care of
mounting /var and /etc if necessary.
  • Loading branch information
Vogtinator committed Oct 7, 2024
1 parent eacd018 commit 70bac1e
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 14 deletions.
21 changes: 20 additions & 1 deletion selinux/98selinux-microos/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
# called by dracut
check() {
test -f /etc/selinux/config || return 1

# Relabelling /etc and /var from the initrd needs support for mounting,
# "chroot mount /..." still loads modules from the initrd.
# Dracut handles /etc already, but for /var we need to DIY.
if [[ -f $dracutsysrootdir/etc/fstab ]]; then
_dev="$(findmnt --fstab --noheadings --output SOURCE /var --tab-file "$dracutsysrootdir/etc/fstab")"
if [[ -n $_dev ]]; then
_fstype="$(findmnt --fstab --noheadings --output FSTYPE /var --tab-file "$dracutsysrootdir/etc/fstab")"
_dev="$(expand_persistent_dev "$_dev")"
_dev="$(readlink -f "$_dev")"
if [[ -b $_dev ]]; then
push_host_devs "$_dev"
if [[ -z ${host_fs_types["$_dev"]} ]]; then
host_fs_types["$_dev"]="$_fstype"
fi
fi
fi
fi

return 0
}

Expand All @@ -14,5 +33,5 @@ depends() {
# called by dracut
install() {
inst_hook pre-pivot 50 "$moddir/selinux-microos-relabel.sh"
inst_multiple chroot cut grep
inst_multiple chroot cut findmnt grep
}
53 changes: 40 additions & 13 deletions selinux/98selinux-microos/selinux-microos-relabel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,19 @@ rd_microos_relabel()
{
info "SELinux: relabeling root filesystem"

root_is_btrfs=
if [ "$(findmnt --noheadings --output FSTYPE --target "$NEWROOT")" = "btrfs" ]; then
root_is_btrfs=y
fi
etc_is_overlay=
if [ "$(findmnt --fstab --noheadings --output FSTYPE /etc --tab-file "${NEWROOT}/etc/fstab")" = "overlay" ]; then
etc_is_overlay=y
fi

# If this doesn't exist because e.g. it's not mounted yet due to a bug
# (boo#1197309), the exclusion is ignored. If it gets mounted during
# the relabel, it gets wrong labels assigned.
if ! [ -d "$NEWROOT/var/lib/overlay" ]; then
if [ -n "$etc_is_overlay" ] && ! [ -d "$NEWROOT/var/lib/overlay" ]; then
warn "ERROR: /var/lib/overlay doesn't exist - /var not mounted (yet)?"
return 1
fi
Expand All @@ -48,24 +57,41 @@ rd_microos_relabel()
ret=1
fi
done
if [ $ret -eq 0 ]; then
# Mount /var and /etc, need to be relabelled as well for booting.
for mp in /var /etc; do
if ! findmnt "${ROOT_SELINUX}${mp}" >/dev/null \
&& findmnt --fstab --output TARGET --tab-file "${ROOT_SELINUX}/etc/fstab" "$mp" >/dev/null; then
chroot "$ROOT_SELINUX" mount "$mp" || ret=1
fi
done
fi
if [ $ret -eq 0 ]; then
info "SELinux: mount root read-write and relabel"
mount -o remount,rw "${ROOT_SELINUX}"
oldrovalue="$(btrfs prop get "${ROOT_SELINUX}" ro | cut -d= -f2)"
btrfs prop set "${ROOT_SELINUX}" ro false
if [ -n "$root_is_btrfs" ]; then
oldrovalue="$(btrfs prop get "${ROOT_SELINUX}" ro | cut -d= -f2)"
btrfs prop set "${ROOT_SELINUX}" ro false
fi
FORCE=
[ -e "${ROOT_SELINUX}"/etc/selinux/.autorelabel ] && FORCE="$(cat "${ROOT_SELINUX}"/etc/selinux/.autorelabel)"
. "${ROOT_SELINUX}"/etc/selinux/config
# Marker when we had relabelled the filesystem. This is relabelled as well.
> "${ROOT_SELINUX}"/etc/selinux/.relabelled
LANG=C chroot "$ROOT_SELINUX" /sbin/setfiles $FORCE -T 0 -e /var/lib/overlay -e /proc -e /sys -e /dev -e /etc "/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts" $(chroot "$ROOT_SELINUX" cut -d" " -f2 /proc/mounts)
# On overlayfs, st_dev isn't consistent so setfiles thinks it's a different mountpoint, ignoring it.
# st_dev changes also on copy-up triggered by setfiles itself, so the only way to relabel properly
# is to list every file explicitly.
# That's not all: There's a kernel bug that security.selinux of parent directories is lost on copy-up (bsc#1210690).
# Work around that by visiting children first and only then the parent directories.
LANG=C chroot "$ROOT_SELINUX" find /etc -depth -exec /sbin/setfiles $FORCE "/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts" \{\} +
btrfs prop set "${ROOT_SELINUX}" ro "${oldrovalue}"
if [ -n "$etc_is_overlay" ]; then
LANG=C chroot "$ROOT_SELINUX" /sbin/setfiles $FORCE -T 0 -e /var/lib/overlay -e /proc -e /sys -e /dev -e /etc "/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts" $(chroot "$ROOT_SELINUX" cut -d" " -f2 /proc/mounts)
# On overlayfs, st_dev isn't consistent so setfiles thinks it's a different mountpoint, ignoring it.
# st_dev changes also on copy-up triggered by setfiles itself, so the only way to relabel properly
# is to list every file explicitly.
# That's not all: There's a kernel bug that security.selinux of parent directories is lost on copy-up (bsc#1210690).
# Work around that by visiting children first and only then the parent directories.
LANG=C chroot "$ROOT_SELINUX" find /etc -depth -exec /sbin/setfiles $FORCE "/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts" \{\} +
else
LANG=C chroot "$ROOT_SELINUX" /sbin/setfiles $FORCE -T 0 -e /proc -e /sys -e /dev "/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts" $(chroot "$ROOT_SELINUX" cut -d" " -f2 /proc/mounts)
fi
if [ -n "$root_is_btrfs" ]; then
btrfs prop set "${ROOT_SELINUX}" ro "${oldrovalue}"
fi
fi

umount -R "${ROOT_SELINUX}"
Expand All @@ -79,8 +105,9 @@ rd_microos_relabel()
return $ret
}

if test -e "$NEWROOT"/.autorelabel -a "$NEWROOT"/.autorelabel -nt "$NEWROOT"/etc/selinux/.relabelled ; then
cp -a "$NEWROOT"/.autorelabel "$NEWROOT"/etc/selinux/.autorelabel
if [ -e "$NEWROOT"/.autorelabel ] && [ "$NEWROOT"/.autorelabel -nt "$NEWROOT"/etc/selinux/.relabelled ]; then
mount -o remount,rw "$NEWROOT" || return 1
cp -a "$NEWROOT"/.autorelabel "$NEWROOT"/etc/selinux/.autorelabel || return 1
rm -f "$NEWROOT"/.autorelabel 2>/dev/null
fi

Expand Down

0 comments on commit 70bac1e

Please sign in to comment.