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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- **`std.audit` now returns coherent entries during concurrent writes.** Its
field accessors previously released the ring lock between category,
resource, and verdict reads, so a wrapped ring could advance and combine
fields from different entries. Each accessor sequence now reads one
thread-local snapshot.
53 changes: 40 additions & 13 deletions runtime/sandbox/aether_audit.c

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

9 changes: 4 additions & 5 deletions runtime/sandbox/aether_audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ void aether_sandbox_audit(const char* category, const char* resource,
int aether_audit_count(void);

// Field accessors for entry `i` (0-based, oldest first). Out-of-range
// `i` yields "" / -1. The returned string points into the ring buffer
// and stays valid only until that slot is overwritten by a later
// aether_sandbox_audit() call or dropped by aether_audit_clear(). A
// caller that records audit entries concurrently with querying should
// copy the string promptly; the std.audit wrappers do.
// `i` yields "" / -1. Reading category, resource, then allowed forms one
// per-thread snapshot, so a concurrent append cannot mix fields from
// different entries. The returned strings stay valid until the next category
// or resource accessor on the same thread; the std.audit wrappers copy them.
const char* aether_audit_entry_category(int i);
const char* aether_audit_entry_resource(int i);
int aether_audit_entry_allowed(int i); // 1 allowed, 0 denied
Expand Down
5 changes: 3 additions & 2 deletions std/audit/module.ae
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ extern string_concat(a: string, b: string) -> string @heap
extern aether_audit_count() -> int

// Field accessors for buffered entry `i` (0-based, oldest first).
// The category/resource strings are borrowed — copy before the slot
// is overwritten. The `entry()` wrapper below does that for you.
// Category, resource, and allowed share one per-thread snapshot when called
// in that order. The strings are borrowed from that snapshot; the `entry()`
// wrapper below copies them before beginning another read.
extern aether_audit_entry_category(i: int) -> string
extern aether_audit_entry_resource(i: int) -> string
extern aether_audit_entry_allowed(i: int) -> int // 1 allowed, 0 denied, -1 out of range
Expand Down
64 changes: 64 additions & 0 deletions tests/integration/audit_entry_snapshot/harness.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,41 @@
#!/bin/sh
# Reading one audit entry must not combine fields from different ring slots
# when another thread overwrites the oldest entry between accessor calls.

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

case "$(uname -s 2>/dev/null)" in
Linux|FreeBSD|Darwin) ;;
*)
echo " [SKIP] audit_entry_snapshot: POSIX thread harness"
exit 0 ;;
esac
if [ ! -f "$ROOT/build/libaether.a" ]; then
echo " [SKIP] audit_entry_snapshot: build/libaether.a not built"
exit 0
fi

TMP="$(cd "$(mktemp -d)" && pwd -P)"
trap 'rm -rf "$TMP"' EXIT
if ! ${CC:-cc} -std=c11 -Wall -Wextra -Werror \
-I"$ROOT/runtime/sandbox" -o "$TMP/harness" "$SCRIPT_DIR/harness.c" \
"$ROOT/build/libaether.a" -lpthread -lm 2>"$TMP/cc.err"; then
echo " [FAIL] audit_entry_snapshot: harness did not compile"
sed 's/^/ /' "$TMP/cc.err" | head -10
exit 1
fi

out="$($TMP/harness 2>&1)"
rc=$?
if [ "$rc" -eq 0 ] && printf '%s' "$out" | grep -q \
'^PASS: audit entry fields come from one snapshot$'; then
echo " [PASS] audit entry fields come from one snapshot"
echo "PASS: audit_entry_snapshot"
exit 0
fi

echo " [FAIL] audit entry fields came from different snapshots"
printf '%s\n' "$out" | sed 's/^/ /' | head -10
echo "FAIL: audit_entry_snapshot"
exit 1
Loading