Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/dotslash-bash-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"outputs": {
"codex-bash": {
"platforms": {
"macos-aarch64": {
"name": "codex-bash-aarch64-apple-darwin.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-bash/bin/bash"
},
"macos-x86_64": {
"name": "codex-bash-x86_64-apple-darwin.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-bash/bin/bash"
},
"linux-x86_64": {
"name": "codex-bash-x86_64-unknown-linux-musl.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-bash/bin/bash"
},
"linux-aarch64": {
"name": "codex-bash-aarch64-unknown-linux-musl.tar.gz",
"format": "tar.gz",
"hash": "sha256",
"path": "codex-bash/bin/bash"
}
}
}
}
}
109 changes: 109 additions & 0 deletions .github/scripts/build-bash-release-artifact.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ "$#" -ne 1 ]]; then
echo "usage: $0 <archive-path>" >&2
exit 1
fi

archive_path="$1"
workspace="${GITHUB_WORKSPACE:?missing GITHUB_WORKSPACE}"
bash_commit="${BASH_COMMIT:?missing BASH_COMMIT}"
bash_patch="${BASH_PATCH:?missing BASH_PATCH}"
temp_root="${RUNNER_TEMP:-/tmp}"
work_root="$(mktemp -d "${temp_root%/}/codex-bash-release.XXXXXX")"
trap 'rm -rf "$work_root"' EXIT

source_root="${work_root}/bash"
package_root="${work_root}/codex-bash"
wrapper_path="${work_root}/exec-wrapper"
stdout_path="${work_root}/stdout.txt"
wrapper_log_path="${work_root}/wrapper.log"
socket_probe_path="${work_root}/socket-probe.txt"

git clone https://git.savannah.gnu.org/git/bash "$source_root"
cd "$source_root"
git checkout "$bash_commit"
git apply "${workspace}/${bash_patch}"

configure_args=(--without-bash-malloc)
if [[ -n "${BASH_HOST:-}" ]]; then
configure_args+=(
--host="$BASH_HOST"
--disable-nls
--disable-readline
--enable-static-link
)
fi
if [[ -n "${MACOSX_DEPLOYMENT_TARGET:-}" ]]; then
# The macOS 15 SDK exposes strchrnul even though it is unavailable on our
# minimum supported macOS version. Use Bash's bundled implementation.
export bash_cv_func_strchrnul_works=no
fi
./configure "${configure_args[@]}"

cores="$(command -v nproc >/dev/null 2>&1 && nproc || getconf _NPROCESSORS_ONLN)"
make -j"${cores}"

# Stand in for codex-execve-wrapper: record each intercepted executable and
# prove that the inherited escalation-socket descriptor is still open.
cat > "$wrapper_path" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
: "${CODEX_WRAPPER_LOG:?missing CODEX_WRAPPER_LOG}"
: "${EXEC_WRAPPER:?missing EXEC_WRAPPER}"
: "${CODEX_ESCALATE_SOCKET:?missing CODEX_ESCALATE_SOCKET}"
printf 'socket-open\n' >&"${CODEX_ESCALATE_SOCKET}"
printf '%s\n' "$@" >> "$CODEX_WRAPPER_LOG"
file="$1"
shift
if [[ "$#" -eq 0 ]]; then
exec "$file"
fi
arg0="$1"
shift
exec -a "$arg0" "$file" "$@"
EOF
chmod +x "$wrapper_path"

# The nested bash and /bin/echo should each pass through EXEC_WRAPPER while
# retaining the same inherited descriptor.
CODEX_WRAPPER_LOG="$wrapper_log_path" \
CODEX_ESCALATE_SOCKET=9 \
EXEC_WRAPPER="$wrapper_path" \
"${source_root}/bash" \
-c "\"${source_root}/bash\" -c '/bin/echo smoke-bash'" \
> "$stdout_path" \
9> "$socket_probe_path"

grep -Fx "smoke-bash" "$stdout_path"
grep -Fx "${source_root}/bash" "$wrapper_log_path"
grep -Fx "/bin/echo" "$wrapper_log_path"
[[ "$(grep -Fxc "socket-open" "$socket_probe_path")" -eq 2 ]]

if [[ -n "${BASH_HOST:-}" ]]; then
file "${source_root}/bash" | grep -F "statically linked"
if readelf -l "${source_root}/bash" | grep -q "INTERP"; then
echo "bash contains an ELF interpreter despite requesting a static build" >&2
exit 1
fi
fi

if [[ -n "${MACOSX_DEPLOYMENT_TARGET:-}" ]]; then
minos="$(otool -l "${source_root}/bash" | awk '$1 == "minos" { print $2; exit }')"
if [[ "$minos" != "$MACOSX_DEPLOYMENT_TARGET" ]]; then
echo "bash has minimum macOS version ${minos}, expected ${MACOSX_DEPLOYMENT_TARGET}" >&2
exit 1
fi
if nm -u "${source_root}/bash" | grep -Eq '[[:space:]]_?strchrnul$'; then
echo "bash references strchrnul, which is unavailable on macOS 12" >&2
exit 1
fi
fi

mkdir -p "$package_root/bin" "$(dirname "${workspace}/${archive_path}")"
cp "${source_root}/bash" "$package_root/bin/bash"
chmod +x "$package_root/bin/bash"

(cd "$work_root" && tar -czf "${workspace}/${archive_path}" codex-bash)
18 changes: 16 additions & 2 deletions .github/scripts/build-zsh-release-artifact.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package_root="${work_root}/codex-zsh"
wrapper_path="${work_root}/exec-wrapper"
stdout_path="${work_root}/stdout.txt"
wrapper_log_path="${work_root}/wrapper.log"
socket_probe_path="${work_root}/socket-probe.txt"

git clone https://git.code.sf.net/p/zsh/code "$source_root"
cd "$source_root"
Expand All @@ -31,11 +32,16 @@ git apply "${workspace}/${zsh_patch}"
cores="$(command -v nproc >/dev/null 2>&1 && nproc || getconf _NPROCESSORS_ONLN)"
make -j"${cores}"

# Stand in for codex-execve-wrapper: record each intercepted executable and
# prove that the inherited escalation-socket descriptor is still open.
cat > "$wrapper_path" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
: "${CODEX_WRAPPER_LOG:?missing CODEX_WRAPPER_LOG}"
printf '%s\n' "$@" > "$CODEX_WRAPPER_LOG"
: "${EXEC_WRAPPER:?missing EXEC_WRAPPER}"
: "${CODEX_ESCALATE_SOCKET:?missing CODEX_ESCALATE_SOCKET}"
printf 'socket-open\n' >&"${CODEX_ESCALATE_SOCKET}"
printf '%s\n' "$@" >> "$CODEX_WRAPPER_LOG"
file="$1"
shift
if [[ "$#" -eq 0 ]]; then
Expand All @@ -47,12 +53,20 @@ exec -a "$arg0" "$file" "$@"
EOF
chmod +x "$wrapper_path"

# The nested zsh and /bin/echo should each pass through EXEC_WRAPPER while
# retaining the same inherited descriptor.
CODEX_WRAPPER_LOG="$wrapper_log_path" \
CODEX_ESCALATE_SOCKET=9 \
EXEC_WRAPPER="$wrapper_path" \
"${source_root}/Src/zsh" -fc '/bin/echo smoke-zsh' > "$stdout_path"
"${source_root}/Src/zsh" \
-fc "\"${source_root}/Src/zsh\" -fc '/bin/echo smoke-zsh'" \
> "$stdout_path" \
9> "$socket_probe_path"

grep -Fx "smoke-zsh" "$stdout_path"
grep -Fx "${source_root}/Src/zsh" "$wrapper_log_path"
grep -Fx "/bin/echo" "$wrapper_log_path"
[[ "$(grep -Fxc "socket-open" "$socket_probe_path")" -eq 2 ]]

mkdir -p "$package_root/bin" "$(dirname "${workspace}/${archive_path}")"
cp "${source_root}/Src/zsh" "$package_root/bin/zsh"
Expand Down
66 changes: 66 additions & 0 deletions .github/scripts/test-shell-exec-wrapper-chain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ "$#" -ne 2 ]]; then
echo "usage: $0 <bash-path> <zsh-path>" >&2
exit 1
fi

bash_path="$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
zsh_path="$(cd "$(dirname "$2")" && pwd)/$(basename "$2")"
temp_root="${RUNNER_TEMP:-/tmp}"
work_root="$(mktemp -d "${temp_root%/}/codex-shell-chain.XXXXXX")"
trap 'rm -rf "$work_root"' EXIT

wrapper_path="${work_root}/exec-wrapper"

# Stand in for codex-execve-wrapper: record each intercepted executable and
# prove that the inherited escalation-socket descriptor is still open.
cat > "$wrapper_path" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
: "${CODEX_WRAPPER_LOG:?missing CODEX_WRAPPER_LOG}"
: "${EXEC_WRAPPER:?missing EXEC_WRAPPER}"
: "${CODEX_ESCALATE_SOCKET:?missing CODEX_ESCALATE_SOCKET}"
printf 'socket-open\n' >&"${CODEX_ESCALATE_SOCKET}"
printf '%s\n' "$@" >> "$CODEX_WRAPPER_LOG"
file="$1"
shift
if [[ "$#" -eq 0 ]]; then
exec "$file"
fi
arg0="$1"
shift
exec -a "$arg0" "$file" "$@"
EOF
chmod +x "$wrapper_path"

run_chain() {
local outer_shell="$1"
local outer_flag="$2"
local inner_shell="$3"
local inner_flag="$4"
local marker="$5"
local wrapper_log="${work_root}/${marker}-wrapper.log"
local socket_probe="${work_root}/${marker}-socket.log"
local stdout="${work_root}/${marker}-stdout.txt"
local command
command="\"${inner_shell}\" ${inner_flag} '/bin/echo ${marker}'"

# The inner shell and /bin/echo should each pass through EXEC_WRAPPER while
# retaining the same inherited descriptor.
CODEX_WRAPPER_LOG="$wrapper_log" \
CODEX_ESCALATE_SOCKET=9 \
EXEC_WRAPPER="$wrapper_path" \
"$outer_shell" "$outer_flag" "$command" > "$stdout" 9> "$socket_probe"

grep -Fx "$marker" "$stdout"
grep -Fx "$inner_shell" "$wrapper_log"
grep -Fx "/bin/echo" "$wrapper_log"
[[ "$(grep -Fxc "socket-open" "$socket_probe")" -eq 2 ]]
}

# Either patched shell may launch the other, so exercise both directions.
run_chain "$bash_path" -c "$zsh_path" -fc bash-zsh-chain
run_chain "$zsh_path" -fc "$bash_path" -c zsh-bash-chain
Loading
Loading