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
10 changes: 7 additions & 3 deletions compiler/codegen/codegen.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- **Deeply nested sandbox blocks now fail closed.** The generated permission
stack silently dropped pushes beyond its 64-slot capacity, so an inner
policy could run under only its outer grants. The logical depth now
continues past the storage limit and refuses checks until matching pops or
unwind restoration returns it to a representable level.
35 changes: 35 additions & 0 deletions tests/integration/sandbox_depth_overflow/prog.ae
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import std.os
import std.sandbox

fn descend(level: int, allow: sandbox.Grants, deny: sandbox.Grants) -> int {
visible = 1
if level == 0 {
sandbox.enforce(deny) callback {
if os.getenv("AE_SANDBOX_DEPTH_SECRET") == null { visible = 0 }
}
return visible
}

sandbox.enforce(allow) callback {
visible = descend(level - 1, allow, deny)
}
return visible
}

main() {
allow = sandbox.new("allow env") {
grant_env("AE_SANDBOX_DEPTH_SECRET")
}
deny = sandbox.new("deny env") {}

visible = descend(64, allow, deny)
println("overflow-visible=${visible}")

restored = 0
if os.getenv("AE_SANDBOX_DEPTH_SECRET") != null { restored = 1 }
println("after-visible=${restored}")

sandbox.free(deny)
sandbox.free(allow)
return visible + (1 - restored)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/sh
# A grant pushed past the fixed stack capacity must refuse checks instead of
# letting the block run under only its less restrictive outer grants.

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
AE="$ROOT/build/ae"

if [ ! -x "$AE" ]; then
echo " [SKIP] sandbox_depth_overflow: build/ae not built"
exit 0
fi

TMP="$(cd "$(mktemp -d)" && pwd -P)"
trap 'rm -rf "$TMP"' EXIT
if ! "$AE" build "$SCRIPT_DIR/prog.ae" -o "$TMP/prog" >"$TMP/build.log" 2>&1; then
echo " [FAIL] sandbox_depth_overflow: probe did not build"
sed 's/^/ /' "$TMP/build.log" | tail -20
exit 1
fi

set +e
out="$(AE_SANDBOX_DEPTH_SECRET=visible "$TMP/prog" 2>&1)"
rc=$?
set -e
if [ "$rc" -eq 0 ] && printf '%s' "$out" | grep -q '^overflow-visible=0$' &&
printf '%s' "$out" | grep -q '^after-visible=1$'; then
echo " [PASS] sandbox stack overflow refuses the inner check"
echo "PASS: sandbox_depth_overflow"
exit 0
fi

echo " [FAIL] sandbox stack overflow dropped the inner policy"
printf '%s\n' "$out" | sed 's/^/ /' | head -10
echo "FAIL: sandbox_depth_overflow (rc=$rc)"
exit 1