Skip to content

Commit 70996b2

Browse files
committed
Address hardening gap analysis
1 parent 7c59e5c commit 70996b2

6 files changed

Lines changed: 303 additions & 4 deletions

File tree

crates/aesynx-arch-x86_64/src/cpu_hardening/cpuid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::CpuHardeningCapabilities;
22

33
pub(super) const CPUID_LEAF_7_EDX_IBRS_IBPB: u32 = 1 << 26;
44
pub(super) const CPUID_LEAF_7_EDX_ARCH_CAPABILITIES: u32 = 1 << 29;
5-
pub(super) const CPUID_AMD_EXTENDED_EBX_IBRS: u32 = 1 << 9;
5+
pub(super) const CPUID_AMD_EXTENDED_EBX_IBRS: u32 = 1 << 14;
66
pub(super) const CPUID_AMD_EXTENDED_EBX_IBPB: u32 = 1 << 12;
77
pub(super) const CPUID_AMD_EXTENDED_EBX_STIBP: u32 = 1 << 15;
88
pub(super) const CPUID_AMD_EXTENDED_EBX_SSBD: u32 = 1 << 24;

crates/aesynx-arch-x86_64/src/cpu_hardening/tests.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,32 @@ fn capability_detection_keeps_intel_and_amd_ibrs_ibpb_paths_distinct() {
123123
assert!(!amd_ibrs.ssbd);
124124
}
125125

126+
#[test]
127+
fn capability_detection_uses_amd_extended_ibrs_bit_14() {
128+
let amd_ibrs_bit_14 = CpuidSnapshot::from_regs(0, 1 << 14, 0, 0);
129+
let amd_unrelated_bit_9 = CpuidSnapshot::from_regs(0, 1 << 9, 0, 0);
130+
131+
let supported = capabilities_from_cpuid(
132+
true,
133+
false,
134+
false,
135+
false,
136+
CpuidSnapshot::ZERO,
137+
amd_ibrs_bit_14,
138+
);
139+
let unsupported = capabilities_from_cpuid(
140+
true,
141+
false,
142+
false,
143+
false,
144+
CpuidSnapshot::ZERO,
145+
amd_unrelated_bit_9,
146+
);
147+
148+
assert!(supported.ibrs);
149+
assert!(!unsupported.ibrs);
150+
}
151+
126152
#[test]
127153
fn strict_hardening_policy_rejects_missing_optional_bits() {
128154
let no_smep = CpuHardeningCapabilities {

docs/RELEASE_PLAN.md

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,6 +2363,126 @@ Exit criteria:
23632363
- Aesynx has a documented path to a small per-core kernel plus isolated
23642364
monitor/services before distributed policy becomes live.
23652365

2366+
### v0.37.8 - Cache-Aware Atomic Fabric Queues
2367+
2368+
Goal:
2369+
2370+
Replace model-only core-to-core queue evidence with the hardware-ordering shape
2371+
required for live multicore endpoints.
2372+
2373+
Rationale:
2374+
2375+
The v0.36/v0.37 IPC smokes prove route validation, sequencing, and fail-closed
2376+
backpressure, but the queue implementation remains sequential model code with
2377+
plain indices. Live AP execution needs queues whose memory layout, ownership,
2378+
cache behavior, and atomic publication protocol are correct on weakly ordered
2379+
architectures as well as x86_64.
2380+
2381+
Deliverables:
2382+
2383+
- Hardware SPSC queue design that removes shared mutable `len` from producer
2384+
and consumer hot paths.
2385+
- Monotonic producer and consumer cursors, each written by exactly one endpoint.
2386+
- Cached remote-cursor observations that are explicitly advisory and refreshed
2387+
through acquire loads.
2388+
- Producer and consumer metadata separated onto distinct cache lines, with an
2389+
option to place endpoint metadata on separate pages when permissions differ.
2390+
- Slot publication protocol:
2391+
- producer writes payload;
2392+
- producer scrubs or initializes authority-bearing padding;
2393+
- producer performs a release store of slot sequence or tail;
2394+
- consumer performs an acquire load before reading payload.
2395+
- Slot reuse protocol with generation or sequence numbers so wraparound cannot
2396+
expose stale payloads.
2397+
- Mandatory zero/scrub-on-vacate policy before a slot can be observed by a
2398+
different trust domain.
2399+
- Doorbell bitmap or equivalent pending-link summary so each core does not have
2400+
to poll every inbound link at high core counts.
2401+
- IPI coalescing and batch receive/send policy.
2402+
- Queue placement policy for NUMA-local allocation and traffic-class
2403+
separation.
2404+
- Separate traffic classes for authority-critical revoke/topology messages,
2405+
best-effort telemetry, and ordinary service requests. Revocation and topology
2406+
control must not sit behind best-effort telemetry in the same FIFO.
2407+
- Per-principal/service credits, deadlines, retry budgets, cancellation, and
2408+
dead-letter records for noisy or stalled peers.
2409+
- Explicit memory-ordering tests and model checks for x86_64, aarch64, and
2410+
RISC-V assumptions. Release/acquire evidence must correspond to actual atomic
2411+
stores/loads, not metadata fields.
2412+
2413+
Verification:
2414+
2415+
- Host model tests prove full, empty, wraparound, stale-slot, and retry cases
2416+
fail closed without payload reuse.
2417+
- Loom/Kani-style or equivalent bounded model tests prove the SPSC publication
2418+
protocol does not permit payload reads before release publication.
2419+
- Cache-line layout tests prove producer and consumer hot metadata do not share
2420+
a cache line.
2421+
- QEMU smoke reports direct-link evidence only after the atomic queue path is
2422+
used by the kernel smoke.
2423+
2424+
Exit criteria:
2425+
2426+
- Aesynx has a queue implementation shape that can be wired to live APs without
2427+
pretending model `Ordering` evidence is a hardware happens-before relation.
2428+
2429+
### v0.37.9 - Strong Revocation And Mapping Invalidation Semantics
2430+
2431+
Goal:
2432+
2433+
Define and model the difference between prospective revocation and strong
2434+
revocation before mappings, DMA, or in-flight endpoint operations can carry
2435+
real authority across domains.
2436+
2437+
Rationale:
2438+
2439+
Incrementing a revocation epoch is enough for later live checks to fail, but it
2440+
does not automatically remove receiver table entries, tear down mappings, flush
2441+
remote TLBs, cancel DMA, cancel in-flight IPC, or prove every core has observed
2442+
the new epoch. Aesynx needs an explicit revoke contract before shared memory,
2443+
driver DMA, or cross-core delegation becomes live.
2444+
2445+
Deliverables:
2446+
2447+
- Two documented revoke classes:
2448+
- Prospective revoke: no operation beginning after the revoke linearization
2449+
point may succeed.
2450+
- Strong revoke: when revoke returns, no stale operation, mapping, DMA
2451+
request, delegated entry, or in-flight endpoint operation can still commit.
2452+
- Revocation messages carry object incarnation, previous epoch, new epoch,
2453+
transaction ID, reason code, coordinator proof, and affected authority class.
2454+
- Distributed prepare/freeze/ack/commit/abort model for strong revocation.
2455+
- Mapping teardown protocol that unmaps every affected address space before
2456+
strong revoke commit.
2457+
- Mandatory local and remote TLB invalidation acknowledgements before a
2458+
permission reduction or unmap is reported complete.
2459+
- DMA quiesce/cancel/drain requirement before strong revocation of device-visible
2460+
memory.
2461+
- In-flight IPC cancellation or replay policy for operations authorized before
2462+
the revoke linearization point.
2463+
- Failure handling for dead cores or domains: timeout leads to quarantine,
2464+
degraded fail-closed state, or system halt depending on authority class.
2465+
- Audit records linking proposal, freeze, acknowledgement, TLB/DMA cleanup,
2466+
commit, abort, and timeout.
2467+
- Redacted diagnostics that expose counts, classes, and reason codes without
2468+
raw object IDs, physical frames, or table slots.
2469+
2470+
Verification:
2471+
2472+
- Host model tests prove prospective revoke rejects every operation starting
2473+
after the linearization point.
2474+
- Host model tests prove strong revoke cannot complete until modeled mappings,
2475+
TLB acknowledgements, DMA ownership, and pending grants are resolved.
2476+
- Timeout tests prove dead participants cannot let stale authority remain
2477+
silently usable.
2478+
- Mapper tests prove permission reduction/unmap cannot be acknowledged until
2479+
the required flush obligation is consumed.
2480+
2481+
Exit criteria:
2482+
2483+
- Revocation semantics are precise enough for live shared memory, driver DMA,
2484+
and cross-core capability transfer to build on them.
2485+
23662486
## Phase 10: Driver Foundation
23672487

23682488
### v0.38.0 - Device Model
@@ -2702,6 +2822,58 @@ Exit criteria:
27022822
- The kernel has one reviewed path for user memory access before userspace can
27032823
pass pointers into kernel services.
27042824

2825+
### v0.44.5 - Domain Transition And Speculation Hardening
2826+
2827+
Goal:
2828+
2829+
Define and smoke-test the CPU and address-space hardening required before ring
2830+
3, mutually distrusting domains, or context switches can be treated as a real
2831+
security boundary.
2832+
2833+
Deliverables:
2834+
2835+
- Correct x86_64 CPUID feature detection for Intel and AMD speculative controls,
2836+
including AMD extended-leaf IBRS bit 14, IBPB bit 12, STIBP bit 15, and SSBD
2837+
bit 24.
2838+
- `IA32_ARCH_CAPABILITIES` field decoding plan for eIBRS/IBRS_ALL, RDCL_NO,
2839+
MDS_NO, TAA_NO, RSBA, and newer vendor-documented controls where available.
2840+
- Context-transition mitigation policy for switching between mutually
2841+
distrusting domains:
2842+
- when IBPB is required;
2843+
- when STIBP is redundant or required;
2844+
- when RSB stuffing or BHB/BHI mitigation is required;
2845+
- when VERW-based MDS/RFDS buffer clearing is required;
2846+
- when L1D flush policy is required.
2847+
- Explicit SMT-domain policy for high-assurance workloads.
2848+
- KPTI or dual-root page-table plan for processors affected by rogue data-cache
2849+
load, with a documented QEMU/general-mode fallback.
2850+
- L1TF hygiene policy: non-present PTEs are all-zero unless a reviewed
2851+
exception exists, and physical page zero must never contain secrets.
2852+
- Hardened syscall/sysret or interrupt-return entry/exit plan with per-core
2853+
TSS/RSP0, swapgs fencing if used, contained user faults, and no reliance on
2854+
compiler-generated prologues for critical transition assembly.
2855+
- Full architectural state-switch plan including SIMD/FPU ownership before
2856+
SSE/AVX is enabled in kernel or user contexts.
2857+
- Trampoline or boot-order policy that enables compatible NX/WP/SMEP/SMAP/UMIP
2858+
protections before untrusted code or APs can execute with the final CR3.
2859+
- Redacted serial markers for supported, requested, applied, and deferred
2860+
hardening controls.
2861+
2862+
Verification:
2863+
2864+
- Host tests cover Intel/AMD CPUID matrices, including the AMD IBRS bit-14
2865+
regression and unrelated-bit rejection.
2866+
- Host tests cover `ARCH_CAPABILITIES` decode cases and strict/general policy
2867+
selection.
2868+
- QEMU smoke reports boolean hardening evidence without raw MSR values.
2869+
- Documentation states which mitigations are active, which are planned, and
2870+
which are not relevant on the current QEMU CPU model.
2871+
2872+
Exit criteria:
2873+
2874+
- The ring-3 path has an explicit security-transition hardening plan and tests
2875+
before user address spaces become a hostile input boundary.
2876+
27052877
## Phase 11: Native Userspace
27062878

27072879
### v0.45.0 - User Address Space
@@ -3268,6 +3440,60 @@ Exit criteria:
32683440

32693441
- AI assistance exists as a constrained shell helper, not an authority source.
32703442

3443+
### v0.61.2 - Metered Asynchronous AI Policy Service
3444+
3445+
Goal:
3446+
3447+
Ensure AI advice can never block scheduler progress, bypass deterministic
3448+
validation, or become a hidden reference monitor.
3449+
3450+
Deliverables:
3451+
3452+
- AI/model execution runs outside ring 0 in a capability-confined policy
3453+
service, not in the scheduler hot path.
3454+
- Model evaluation has explicit fuel, deadline, memory, and output-size limits.
3455+
- Manifest step and memory ceilings are consumed by the evaluator, not only
3456+
stored as metadata.
3457+
- Kernel scheduling path never waits synchronously for model output. Advice is
3458+
accepted only if already available and still fresh.
3459+
- Advice records carry topology epoch, task incarnation, model version, expiry,
3460+
and confidence bounded by the validated manifest.
3461+
- Kernel-side validator is total and bounded:
3462+
- computes the finite admissible action set for the current scheduler state;
3463+
- rejects stale topology/task epochs;
3464+
- rejects invalid cores, ownership violations, affinity violations, and
3465+
migration-budget violations;
3466+
- executes deterministic fallback when advice is missing, stale, invalid, or
3467+
over budget.
3468+
- Formal scheduler invariant statement: every admissible action preserves task
3469+
ownership, queue membership, budget accounting, and security-domain placement
3470+
constraints.
3471+
- Task time budgets are decremented or explicitly documented as advisory until
3472+
preemption lands.
3473+
- Telemetry buffer-full behavior cannot stop scheduling. Noncritical telemetry
3474+
drops or overwrites records with a loss counter; security audit events use a
3475+
separate reserved channel with an explicit fail-open/fail-closed policy.
3476+
- OS-world trace emission targets zero allocation, zero locking, and zero copy
3477+
on the normal event path: per-core single-writer binary rings, read-only
3478+
collector mappings, sequence gaps, redaction at export, and user-space hash
3479+
chaining or Merkle aggregation for persistent tamper evidence.
3480+
3481+
Verification:
3482+
3483+
- Host tests prove invalid, stale, over-budget, or unavailable advice falls
3484+
back without blocking dispatch.
3485+
- Host tests prove a full noncritical telemetry buffer increments loss and does
3486+
not prevent task dispatch.
3487+
- Host tests prove advice cannot select an invalid core or migrate a task
3488+
outside allowed affinity/security-domain policy.
3489+
- QEMU smoke proves the scheduler continues with AI disabled, model timeout,
3490+
and telemetry loss counters.
3491+
3492+
Exit criteria:
3493+
3494+
- AI is a bounded proposal source, and deterministic scheduler safety does not
3495+
depend on model liveness or correctness.
3496+
32713497
## Phase 15: Integration And 1.0 Hardening
32723498

32733499
### v0.62.0 - QEMU Smoke Suite

docs/memory-model-roadmap.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ Separate capabilities should exist for:
8888
No service should gain executable, DMA, persistent, or cross-service sharing
8989
rights by accident.
9090

91+
Production mapping is one reference-monitor operation. A caller should not
92+
separately authorize a `MemoryMapRequest`, extract raw addresses, and then call
93+
the mapper with ordinary physical/virtual addresses by convention. The live map
94+
path must consume a checked proof that composes:
95+
96+
- memory-object authority over backing object offset and length;
97+
- address-space authority over the destination virtual range;
98+
- requested access rights and cache/device/confidential attributes;
99+
- executable/JIT policy authority where applicable;
100+
- current object generation and revocation epoch;
101+
- address-space incarnation and ASID/PCID context.
102+
103+
Permission reduction and unmap also create TLB obligations. A live mapper must
104+
not report success to callers until required local and remote invalidation
105+
acknowledgements have completed or the operation has failed closed into a
106+
documented quarantine/degraded state.
107+
91108
Low-level raw frame allocation is different from authority to use memory. The
92109
Barrelfish experience is a warning here: making every physical-memory operation
93110
a fine-grained, globally coordinated capability protocol adds complexity and

docs/multikernel-fabric-roadmap.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ The fabric protocol is the internal network of Aesynx. It needs:
9494
No Rust-specific memory layout should cross the fabric boundary unless the
9595
sender and receiver are proven to use the same ABI and trust domain.
9696

97+
Live core-to-core queues are not the same as the current sequential model. A
98+
production SPSC link needs:
99+
100+
- No shared hot-path `len` field written by both producer and consumer.
101+
- Monotonic cursors where each cursor has exactly one writer.
102+
- Cached remote cursor observations refreshed through acquire loads.
103+
- Producer and consumer metadata on separate cache lines, or separate pages
104+
when endpoint permissions differ.
105+
- Payload write followed by release publication, and acquire observation before
106+
payload read.
107+
- Slot generation/sequence numbers for wraparound and reuse.
108+
- Scrub-on-vacate before authority-bearing payload storage can be observed by a
109+
different trust domain.
110+
- Doorbell bitmaps, IPI coalescing, batching, and traffic-class separation so a
111+
noisy telemetry path cannot delay revocation or topology-control messages.
112+
97113
## Replicated Authority State
98114

99115
A true multikernel cannot rely on one global lock for authority state.
@@ -119,6 +135,18 @@ code on every core. The local kernel validates and applies the final local
119135
mechanism only after the authority protocol has produced a bounded, auditable
120136
decision.
121137

138+
Revocation has two classes:
139+
140+
- Prospective revocation: no operation beginning after the linearization point
141+
may succeed.
142+
- Strong revocation: when revoke returns, no stale operation, mapping, DMA
143+
request, delegated entry, or in-flight endpoint operation may still commit.
144+
145+
Strong revocation requires more than an epoch bump. It needs freeze/ack/commit
146+
or equivalent agreement, mapping teardown, local and remote TLB invalidation
147+
acknowledgements, DMA quiesce/cancel/drain, in-flight IPC cancellation or
148+
replay rules, and timeout handling for failed peers.
149+
122150
## Topology And Routing
123151

124152
Early Aesynx can send direct core-to-core messages. A mature fabric should learn

0 commit comments

Comments
 (0)