Replace planted policy directory symlinks instead of following them

install -d follows a managed or distribution symlink and would chmod the target. Unlink those paths first, and treat a dangling symlink as a directory the migration still has to repair.
This commit is contained in:
acrogenesis
2026-08-25 12:14:52 -06:00
parent bebe19bc70
commit 44a186afe4
3 changed files with 53 additions and 6 deletions
+6 -3
View File
@@ -68,7 +68,7 @@ browser_policy_purge_dir() {
browser_policy_dir_hardened() {
local dir=$1
[[ -d $dir ]] || return 1
[[ -d $dir && ! -L $dir ]] || return 1
[[ $(stat -c '%a' "$dir") == "2775" ]] || return 1
[[ $(stat -c '%U' "$dir") == "root" ]] || return 1
[[ $(stat -c '%G' "$dir") == $BROWSER_POLICY_GROUP ]] || return 1
@@ -116,6 +116,9 @@ browser_policy_setup_dir() {
local dir=$1
browser_policy_setup_parents_for "$dir"
if [[ -L $dir || ( -e $dir && ! -d $dir ) ]]; then
as_root rm -rf -- "$dir"
fi
as_root install -d -m 2775 -o root -g "$BROWSER_POLICY_GROUP" "$dir"
browser_policy_purge_dir "$dir"
}
@@ -229,7 +232,7 @@ browser_policy_firefox_policy_file_ok() {
browser_policy_firefox_hardened() {
local dir=$1
[[ -d $dir ]] || return 1
[[ -d $dir && ! -L $dir ]] || return 1
[[ $(stat -c '%a' "$dir") == "755" ]] || return 1
[[ $(stat -c '%U' "$dir") == "root" ]] || return 1
browser_policy_firefox_policy_file_ok "$dir/policies.json"
@@ -246,7 +249,7 @@ browser_policy_setup_firefox_distribution() {
local distribution_dir=$1
local policies=${2:-$OMARCHY_PATH/default/firefox/policies.json}
as_root install -d -m 0755 -o root -g root "$distribution_dir"
browser_policy_setup_parent "$distribution_dir"
browser_policy_purge_dir "$distribution_dir"
browser_policy_install_firefox_policies "$distribution_dir" "$policies"
}
+3 -3
View File
@@ -7,7 +7,7 @@ browser_policy_grant_user "${USER:-$(id -un)}"
repaired=0
for dir in "${BROWSER_POLICY_MANAGED_DIRS[@]}"; do
[[ -d $dir ]] || continue
[[ -d $dir || -L $dir ]] || continue
if browser_policy_dir_hardened "$dir" && browser_policy_parents_hardened "$dir"; then
continue
fi
@@ -20,9 +20,9 @@ if (( repaired )); then
fi
for dir in "${BROWSER_POLICY_FIREFOX_DIRS[@]}"; do
[[ -d $dir ]] || continue
[[ -d $dir || -L $dir ]] || continue
browser_policy_firefox_hardened "$dir" && continue
as_root install -d -m 0755 -o root -g root "$dir"
browser_policy_setup_parent "$dir"
browser_policy_purge_dir "$dir"
if ! browser_policy_firefox_policy_file_ok "$dir/policies.json"; then
browser_policy_install_firefox_policies "$dir"
+44
View File
@@ -213,6 +213,50 @@ grep -Fxq 'planted' "$symlink_root/attacker/policies/managed/evil.json" ||
BROWSER_POLICY_PARENT_DIRS=("${saved_parent_dirs[@]}")
pass "policy setup does not follow a planted parent symlink"
leaf_link_root=$test_tmp/leaf-link
mkdir -p "$leaf_link_root/etc/chromium/policies" "$leaf_link_root/attacker"
printf 'planted\n' >"$leaf_link_root/attacker/evil.json"
chmod 755 "$leaf_link_root/etc/chromium" "$leaf_link_root/etc/chromium/policies"
ln -s "$leaf_link_root/attacker" "$leaf_link_root/etc/chromium/policies/managed"
BROWSER_POLICY_PARENT_DIRS=(
"$leaf_link_root/etc/chromium"
"$leaf_link_root/etc/chromium/policies"
)
as_root() { unprivileged_as_root "$@"; }
if browser_policy_dir_hardened "$leaf_link_root/etc/chromium/policies/managed"; then
fail "a planted managed symlink is not treated as hardened"
fi
browser_policy_setup_dir "$leaf_link_root/etc/chromium/policies/managed"
[[ ! -L $leaf_link_root/etc/chromium/policies/managed ]] ||
fail "setup replaces a planted managed symlink"
[[ -d $leaf_link_root/etc/chromium/policies/managed && ! -L $leaf_link_root/etc/chromium/policies/managed ]] ||
fail "setup recreates managed as a real directory"
[[ ! -e $leaf_link_root/etc/chromium/policies/managed/evil.json ]] ||
fail "setup does not keep policy that lived behind a planted managed symlink"
grep -Fxq 'planted' "$leaf_link_root/attacker/evil.json" ||
fail "replacing a managed symlink does not delete the symlink target"
BROWSER_POLICY_PARENT_DIRS=("${saved_parent_dirs[@]}")
pass "policy setup does not follow a planted managed symlink"
fx_link_root=$test_tmp/fx-link
mkdir -p "$fx_link_root/attacker" "$fx_link_root/opt"
printf 'planted\n' >"$fx_link_root/attacker/policies.json"
ln -s "$fx_link_root/attacker" "$fx_link_root/opt/zen"
as_root() { unprivileged_as_root "$@"; }
if browser_policy_firefox_hardened "$fx_link_root/opt/zen"; then
fail "a planted Firefox distribution symlink is not treated as hardened"
fi
browser_policy_setup_firefox_distribution "$fx_link_root/opt/zen" ||
fail "Firefox setup replaces a planted distribution symlink"
[[ ! -L $fx_link_root/opt/zen ]] || fail "Firefox setup unlinks a planted distribution symlink"
[[ -d $fx_link_root/opt/zen && ! -L $fx_link_root/opt/zen ]] ||
fail "Firefox setup recreates the distribution directory"
[[ -f $fx_link_root/opt/zen/policies.json && ! -L $fx_link_root/opt/zen/policies.json ]] ||
fail "Firefox setup writes policies.json into the recreated directory"
grep -Fxq 'planted' "$fx_link_root/attacker/policies.json" ||
fail "replacing a Firefox distribution symlink does not delete the symlink target"
pass "Firefox setup does not follow a planted distribution symlink"
[[ $(browser_policy_theme_hex "242,240,229") == "#f2f0e5" ]] ||
fail "theme colour converts an RGB triple to hex"
[[ $(browser_policy_theme_hex $'14,31,41\n') == "#0e1f29" ]] ||