Find the caller of the Bash startup check the way /proc numbers it
The check read /proc/$$/cmdline. arch-chroot runs its command in a new PID namespace beneath the outer /proc, where $$ names no process or someone else's, so every bash -p entrypoint was rejected there with status 126. The installer met this as soon as one was called at install time: install/config/thunderbolt-authorization.sh runs omarchy-thunderbolt-authorization-admin, and the edge ISO stopped in "Configuring system" with "/proc/219/cmdline: No such file or directory". The check runs in a child of the caller, so read the parent from that child's /proc/self/stat, which is given in the numbering of the /proc it is read through. Outside a PID namespace that is $$, as before.
This commit is contained in:
1 parent
7cc6a55f24
commit
dd05114e95
2 files changed
+49
-3
No files matched your search
@@ -10,13 +10,18 @@ fi
|
|||||||
|
|
||||||
omarchy_security_require_privileged_bash_startup() {
|
omarchy_security_require_privileged_bash_startup() {
|
||||||
[[ $- == *p* ]] || return 1
|
[[ $- == *p* ]] || return 1
|
||||||
|
# The caller is this check's parent, under the number this /proc gives it.
|
||||||
|
# arch-chroot runs the installer in a new PID namespace beneath the outer
|
||||||
|
# /proc, where $$ names no process, or someone else's.
|
||||||
/usr/bin/env -i /usr/bin/bash -p -c '
|
/usr/bin/env -i /usr/bin/bash -p -c '
|
||||||
mapfile -d "" -t argv <"/proc/$1/cmdline" || exit 1
|
stat=$(</proc/self/stat) || exit 1
|
||||||
executable=$(/usr/bin/readlink -e -- "/proc/$1/exe") || exit 1
|
read -r _ caller _ <<<"${stat##*) }"
|
||||||
|
mapfile -d "" -t argv <"/proc/$caller/cmdline" || exit 1
|
||||||
|
executable=$(/usr/bin/readlink -e -- "/proc/$caller/exe") || exit 1
|
||||||
[[ $executable == "/usr/bin/bash" &&
|
[[ $executable == "/usr/bin/bash" &&
|
||||||
( ${argv[0]:-} == "/bin/bash" || ${argv[0]:-} == "/usr/bin/bash" ) &&
|
( ${argv[0]:-} == "/bin/bash" || ${argv[0]:-} == "/usr/bin/bash" ) &&
|
||||||
${argv[1]:-} == "-p" ]]
|
${argv[1]:-} == "-p" ]]
|
||||||
' omarchy-bash-startup "$$"
|
' omarchy-bash-startup
|
||||||
}
|
}
|
||||||
|
|
||||||
omarchy_security_sanitize_bash_environment() {
|
omarchy_security_sanitize_bash_environment() {
|
||||||
|
|||||||
Executable
+41
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||||
|
|
||||||
|
test_tmp=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$test_tmp"' EXIT
|
||||||
|
|
||||||
|
cat >"$test_tmp/entrypoint" <<SH
|
||||||
|
#!/bin/bash -p
|
||||||
|
source "$ROOT/bin/omarchy-security-functions"
|
||||||
|
omarchy_security_require_privileged_bash_startup
|
||||||
|
SH
|
||||||
|
chmod +x "$test_tmp/entrypoint"
|
||||||
|
|
||||||
|
"$test_tmp/entrypoint" || fail "a script started as bash -p passes the startup check"
|
||||||
|
( "$test_tmp/entrypoint" ) || fail "the startup check passes from a subshell"
|
||||||
|
pass "a script started as bash -p passes the startup check"
|
||||||
|
|
||||||
|
if /usr/bin/bash -c "set -p; source '$ROOT/bin/omarchy-security-functions'; omarchy_security_require_privileged_bash_startup"; then
|
||||||
|
fail "bash that only turned -p on later is rejected"
|
||||||
|
fi
|
||||||
|
if /usr/bin/bash "$test_tmp/entrypoint"; then
|
||||||
|
fail "a script not started with -p is rejected"
|
||||||
|
fi
|
||||||
|
pass "bash not started with -p is rejected"
|
||||||
|
|
||||||
|
# arch-chroot runs the installer in a new PID namespace under the outer /proc,
|
||||||
|
# so the caller's own PID is not the number /proc knows it by.
|
||||||
|
in_new_pid_namespace=(unshare --user --map-root-user --fork --pid)
|
||||||
|
if "${in_new_pid_namespace[@]}" /usr/bin/true 2>/dev/null; then
|
||||||
|
"${in_new_pid_namespace[@]}" /usr/bin/bash -c "for i in {1..50}; do /usr/bin/true; done; '$test_tmp/entrypoint'; exit" </dev/null ||
|
||||||
|
fail "the startup check passes in a new PID namespace under the outer /proc"
|
||||||
|
if "${in_new_pid_namespace[@]}" /usr/bin/bash -c "/usr/bin/bash '$test_tmp/entrypoint'; exit" </dev/null; then
|
||||||
|
fail "a script not started with -p is rejected in a new PID namespace"
|
||||||
|
fi
|
||||||
|
pass "the startup check sees its caller in a new PID namespace, as under arch-chroot"
|
||||||
|
else
|
||||||
|
skip "a new PID namespace needs unprivileged user namespaces"
|
||||||
|
fi
|
||||||
Reference in new issue
Block a user