From dc909e6f0bc26da91e6fcf586f05d32daf96ac5d Mon Sep 17 00:00:00 2001 From: Markus Hilger Date: Fri, 30 Oct 2026 09:43:18 +0100 Subject: [PATCH] Label overlay upper layer of diskless images for SELinux With a tethered root (and on EL8 always), the initramfs writes the overlay upper layer before the SELinux policy is loaded, so those files are unlabeled_t. On a captured enforcing image sshd-keygen then cannot search / and the node comes up without sshd. Label exactly the upper layer paths with matchpathcon and chcon. setfiles would recurse into the merged tree and restorecon is a no-op before policy load. Built images have SELinux disabled and skip this. --- .../profiles/default/scripts/imageboot.sh | 31 +++++++++++++++++++ .../profiles/default/scripts/imageboot.sh | 31 +++++++++++++++++++ .../profiles/default/scripts/imageboot.sh | 31 +++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/confluent_osdeploy/el10-diskless/profiles/default/scripts/imageboot.sh b/confluent_osdeploy/el10-diskless/profiles/default/scripts/imageboot.sh index 208a4e4c..b47270da 100644 --- a/confluent_osdeploy/el10-diskless/profiles/default/scripts/imageboot.sh +++ b/confluent_osdeploy/el10-diskless/profiles/default/scripts/imageboot.sh @@ -140,6 +140,37 @@ set_selinux_context system_u:object_r:bin_t:s0 /sysroot/opt/confluent/bin/onboot set_selinux_context system_u:object_r:bin_t:s0 /sysroot/opt/confluent/bin/apiclient ln -s /etc/systemd/system/onboot.service /sysroot/etc/systemd/system/multi-user.target.wants/onboot.service cp /etc/confluent/functions /sysroot/etc/confluent/functions +if [ $TETHERED -eq 1 ] && [ -x /sysroot/usr/sbin/matchpathcon ] && grep -Eq '^SELINUX=(enforcing|permissive)' /sysroot/etc/selinux/config 2> /dev/null; then + # Files written to the upper layer before policy load are unlabeled. + # Label only those, using globstar since the initramfs has no find. + selinuxpolicy=$(sed -n 's/^SELINUXTYPE=//p' /sysroot/etc/selinux/config) + shopt -s globstar dotglob nullglob + relabel=() + if [ -f /tmp/mountparts.sh ]; then + overlayparts=$(awk '{print $3}' /tmp/mountparts.sh) + else + overlayparts=/mnt/remote + fi + for srcmount in $overlayparts; do + upperdir=/mnt/overlay/upper + if [ -f /tmp/mountparts.sh ]; then + upperdir=/mnt/overlay${srcmount}/upper + fi + prefix=${srcmount#/mnt/remote} + prefix=${prefix%/} + relabel+=("${prefix:-/}") + for relpath in "$upperdir"/**; do + relabel+=("$prefix${relpath#$upperdir}") + done + done + shopt -u globstar dotglob nullglob + # Not setfiles (recurses) or restorecon (no-op before policy load). + chroot /sysroot /usr/sbin/matchpathcon -f /etc/selinux/$selinuxpolicy/contexts/files/file_contexts "${relabel[@]}" | while IFS=$'\t' read -r relpath context; do + if [ "$context" != "<>" ]; then + chcon -h "$context" "/sysroot$relpath" + fi + done +fi if grep installtodisk /proc/cmdline > /dev/null; then . /etc/confluent/functions run_remote installimage diff --git a/confluent_osdeploy/el8-diskless/profiles/default/scripts/imageboot.sh b/confluent_osdeploy/el8-diskless/profiles/default/scripts/imageboot.sh index 322cd988..481edf80 100644 --- a/confluent_osdeploy/el8-diskless/profiles/default/scripts/imageboot.sh +++ b/confluent_osdeploy/el8-diskless/profiles/default/scripts/imageboot.sh @@ -128,6 +128,37 @@ set_selinux_context system_u:object_r:bin_t:s0 /sysroot/opt/confluent/bin/onboot set_selinux_context system_u:object_r:bin_t:s0 /sysroot/opt/confluent/bin/apiclient ln -s /etc/systemd/system/onboot.service /sysroot/etc/systemd/system/multi-user.target.wants/onboot.service cp /etc/confluent/functions /sysroot/etc/confluent/functions +if [ -x /sysroot/usr/sbin/matchpathcon ] && grep -Eq '^SELINUX=(enforcing|permissive)' /sysroot/etc/selinux/config 2> /dev/null; then + # Files written to the upper layer before policy load are unlabeled. + # Label only those, using globstar since the initramfs has no find. + selinuxpolicy=$(sed -n 's/^SELINUXTYPE=//p' /sysroot/etc/selinux/config) + shopt -s globstar dotglob nullglob + relabel=() + if [ -f /tmp/mountparts.sh ]; then + overlayparts=$(awk '{print $3}' /tmp/mountparts.sh) + else + overlayparts=/mnt/remote + fi + for srcmount in $overlayparts; do + upperdir=/mnt/overlay/upper + if [ -f /tmp/mountparts.sh ]; then + upperdir=/mnt/overlay${srcmount}/upper + fi + prefix=${srcmount#/mnt/remote} + prefix=${prefix%/} + relabel+=("${prefix:-/}") + for relpath in "$upperdir"/**; do + relabel+=("$prefix${relpath#$upperdir}") + done + done + shopt -u globstar dotglob nullglob + # Not setfiles (recurses) or restorecon (no-op before policy load). + chroot /sysroot /usr/sbin/matchpathcon -f /etc/selinux/$selinuxpolicy/contexts/files/file_contexts "${relabel[@]}" | while IFS=$'\t' read -r relpath context; do + if [ "$context" != "<>" ]; then + chcon -h "$context" "/sysroot$relpath" + fi + done +fi if grep installtodisk /proc/cmdline > /dev/null; then . /etc/confluent/functions run_remote installimage diff --git a/confluent_osdeploy/el9-diskless/profiles/default/scripts/imageboot.sh b/confluent_osdeploy/el9-diskless/profiles/default/scripts/imageboot.sh index 7ca1f1e9..31bfd774 100644 --- a/confluent_osdeploy/el9-diskless/profiles/default/scripts/imageboot.sh +++ b/confluent_osdeploy/el9-diskless/profiles/default/scripts/imageboot.sh @@ -142,6 +142,37 @@ set_selinux_context system_u:object_r:bin_t:s0 /sysroot/opt/confluent/bin/onboot set_selinux_context system_u:object_r:bin_t:s0 /sysroot/opt/confluent/bin/apiclient ln -s /etc/systemd/system/onboot.service /sysroot/etc/systemd/system/multi-user.target.wants/onboot.service cp /etc/confluent/functions /sysroot/etc/confluent/functions +if [ $TETHERED -eq 1 ] && [ -x /sysroot/usr/sbin/matchpathcon ] && grep -Eq '^SELINUX=(enforcing|permissive)' /sysroot/etc/selinux/config 2> /dev/null; then + # Files written to the upper layer before policy load are unlabeled. + # Label only those, using globstar since the initramfs has no find. + selinuxpolicy=$(sed -n 's/^SELINUXTYPE=//p' /sysroot/etc/selinux/config) + shopt -s globstar dotglob nullglob + relabel=() + if [ -f /tmp/mountparts.sh ]; then + overlayparts=$(awk '{print $3}' /tmp/mountparts.sh) + else + overlayparts=/mnt/remote + fi + for srcmount in $overlayparts; do + upperdir=/mnt/overlay/upper + if [ -f /tmp/mountparts.sh ]; then + upperdir=/mnt/overlay${srcmount}/upper + fi + prefix=${srcmount#/mnt/remote} + prefix=${prefix%/} + relabel+=("${prefix:-/}") + for relpath in "$upperdir"/**; do + relabel+=("$prefix${relpath#$upperdir}") + done + done + shopt -u globstar dotglob nullglob + # Not setfiles (recurses) or restorecon (no-op before policy load). + chroot /sysroot /usr/sbin/matchpathcon -f /etc/selinux/$selinuxpolicy/contexts/files/file_contexts "${relabel[@]}" | while IFS=$'\t' read -r relpath context; do + if [ "$context" != "<>" ]; then + chcon -h "$context" "/sysroot$relpath" + fi + done +fi if grep installtodisk /proc/cmdline > /dev/null; then . /etc/confluent/functions run_remote installimage