[Security] Complete Plymouth publication coverage

Keep SDDM color substitution collision-free for White themes, based on the fix proposed in #8469.

Co-authored-by: itz4blitz <itz4blitz@users.noreply.github.com>
This commit is contained in:
Afonso Oliveira
2026-08-29 14:45:17 +02:00
committed by Erik Melton
co-authored by itz4blitz
parent 0f15e2330f
commit 20a23b8c16
2 changed files with 39 additions and 6 deletions
+7 -2
View File
@@ -135,9 +135,14 @@ if ! $refresh_default; then
magick "$plymouth_stage/$asset" -channel RGB +level-colors "#$text_hex","#$text_hex" "$plymouth_stage/$asset" magick "$plymouth_stage/$asset" -channel RGB +level-colors "#$text_hex","#$text_hex" "$plymouth_stage/$asset"
done done
# Substitute through unique tokens. Otherwise White's #ffffff background is
# immediately mistaken for the template's text placeholder by the next sed
# expression and rewritten to black.
sed -i \ sed -i \
-e "s/#1a1b26/#$bg_hex/g" \ -e 's/#1a1b26/#__OMARCHY_SDDM_BG__/g' \
-e "s/#ffffff/#$text_hex/g" \ -e 's/#ffffff/#__OMARCHY_SDDM_TEXT__/g' \
-e "s/#__OMARCHY_SDDM_BG__/#$bg_hex/g" \
-e "s/#__OMARCHY_SDDM_TEXT__/#$text_hex/g" \
"$sddm_stage/Main.qml" "$sddm_stage/Main.qml"
for asset in bullet.png entry.png lock.png; do for asset in bullet.png entry.png lock.png; do
+32 -4
View File
@@ -22,6 +22,15 @@ plymouth_theme_assets=(
plymouth_default_assets=("${plymouth_theme_assets[@]}" logos/oma.png) plymouth_default_assets=("${plymouth_theme_assets[@]}" logos/oma.png)
sddm_theme_assets=(Main.qml bullet.png entry-failed.png entry.png lock-failed.png lock.png logo.png) sddm_theme_assets=(Main.qml bullet.png entry-failed.png entry.png lock-failed.png lock.png logo.png)
# Keep the refresh allowlist synchronized with every packaged Plymouth asset.
# An added default file must make this test fail until its publication contract
# is explicitly reviewed and included above.
packaged_plymouth_assets=$(find "$ROOT/default/plymouth" -type f -printf '%P\n' | LC_ALL=C sort)
allowlisted_plymouth_assets=$(printf '%s\n' "${plymouth_default_assets[@]}" | LC_ALL=C sort)
[[ $packaged_plymouth_assets == "$allowlisted_plymouth_assets" ]] ||
fail "Plymouth refresh allowlist differs from the packaged asset set" "$packaged_plymouth_assets"
pass "Plymouth refresh allowlist covers every packaged asset"
# omarchy-plymouth-set-by-theme hands over a theme's unlock.png from # omarchy-plymouth-set-by-theme hands over a theme's unlock.png from
# ~/.config/omarchy/themes. Both installed copies are world-readable, so a # ~/.config/omarchy/themes. Both installed copies are world-readable, so a
# symlink there must not republish whatever it points at. # symlink there must not republish whatever it points at.
@@ -279,9 +288,9 @@ setup_run() {
ln -s "$legacy_victim" "$sddm/logo.svg" ln -s "$legacy_victim" "$sddm/logo.svg"
} }
run_set() { run_set_colors() {
local requested_umask="$1" local requested_umask="$1" background="$2" text="$3"
shift shift 3
( (
umask "$requested_umask" umask "$requested_umask"
PATH="$fake_bin:$ROOT/bin:$PATH" \ PATH="$fake_bin:$ROOT/bin:$PATH" \
@@ -294,10 +303,16 @@ run_set() {
TEST_LEAK_LOG="$leak_log" \ TEST_LEAK_LOG="$leak_log" \
TEST_MUTATE_LOG="$mutate_log" \ TEST_MUTATE_LOG="$mutate_log" \
"$@" \ "$@" \
/bin/bash "$ROOT/bin/omarchy-plymouth-set" '#1d2021' '#ebdbb2' "$test_tmp/logo.png" /bin/bash "$ROOT/bin/omarchy-plymouth-set" "$background" "$text" "$test_tmp/logo.png"
) )
} }
run_set() {
local requested_umask="$1"
shift
run_set_colors "$requested_umask" '#1d2021' '#ebdbb2' "$@"
}
assert_no_temporary_files() { assert_no_temporary_files() {
local directory="$1" leftovers local directory="$1" leftovers
leftovers=$(find "$directory" -name '.*.omarchy-new.*' -print) leftovers=$(find "$directory" -name '.*.omarchy-new.*' -print)
@@ -345,6 +360,19 @@ done
pass "every Plymouth and SDDM destination is atomically replaced with mode 0644 across restrictive umasks" pass "every Plymouth and SDDM destination is atomically replaced with mode 0644 across restrictive umasks"
# White uses #ffffff behind #000000 text. A direct two-expression sed first
# writes the white background and then consumes it as if it were the template's
# text placeholder, producing a black-on-black greeter.
setup_run
output=$(run_set_colors 022 '#ffffff' '#000000' env 2>&1)
status=$?
(( status == 0 )) || fail "White theme publishes through the safe asset pipeline" "$output"
grep -Fq 'color: "#ffffff"' "$sddm/Main.qml" || fail "White theme preserves its SDDM background color"
if grep -Fq '__OMARCHY_SDDM_' "$sddm/Main.qml"; then
fail "SDDM color substitution left an intermediate token behind"
fi
pass "White theme keeps a white SDDM background instead of becoming black-on-black"
# Swap the first staged source to an unreadable file after all hashes have been # Swap the first staged source to an unreadable file after all hashes have been
# recorded but in the DEBUG hook immediately before Bash opens the redirection. # recorded but in the DEBUG hook immediately before Bash opens the redirection.
# The caller-side open must fail, so sudo never starts and nothing is published. # The caller-side open must fail, so sudo never starts and nothing is published.