This is the largest stability and security release Aegis has had: roughly 50 verified fixes in one pass, including the multi-core scheduling bug that had defeated every attempt to fix it for months. It was found, root-caused, fixed, and proven — on real hardware. I want to write up both what shipped and how, because the how is unusual.
How this release was built
1.5.0 came out of a single overnight run by an autonomous team of agents — five working specific domains (SMP/concurrency, memory management, the syscall boundary, networking/signals, the filesystem) plus a dedicated integration agent that merged each fix as it landed, rebuilt the whole tree, and re-ran the test suite continuously. Every fix had to clean-build with warnings-as-errors, pass the boot oracle and the coreutils suite, and survive a multi-core stress amplifier before it was allowed to count. The team found and fixed bugs faster than I could have triaged them alone, and — more importantly — caught each other’s mistakes. Twice, two agents in different domains independently flagged and fixed the same underlying bug, which is about the strongest signal you can get that it was real.
I’ll be honest that I went in skeptical about how much real, verified work would come out the other end versus plausible-looking churn. The answer was: a lot, and the verification discipline held. The whole integrated set passed a 30-out-of-30 multi-core stress batch and a full GUI/CLI test suite with zero real regressions, and then I booted it on bare metal and it came up clean.
The headliner: one task, two CPUs
Aegis has had multi-core scheduling implemented for a while, but gated off by default behind a flag, because turning it on produced an intermittent kernel crash during heavy process startup — roughly one boot in four. The crashes were maddening: kernel panics with the instruction pointer jumped into garbage, page-table-shaped values sprayed across kernel stacks, faults that pointed a dozen different directions. Every one looked like a different memory-corruption bug. I’d chased it as a stale-TLB problem, a use-after-free in the allocator, a missing barrier — and a real TLB bug was found and fixed along the way, which helped but didn’t stop it.
The actual root cause was simpler and nastier than any of those: under load, the scheduler could pick the same task to run on two CPUs at the same time. One process, with one kernel stack, executing on two cores simultaneously — each core saving its register context onto the shared stack, stomping the other. That’s why the wreckage looked like “wrong memory everywhere”: it was the stack scribbling over itself with CPU register state, which is full of pointer-shaped and flag-shaped values that resemble corrupted page tables. Three places in the scheduler chose the next task to run without first checking it wasn’t already running elsewhere. The fix is a one-line guard at each. Result: zero crashes across about 200 boots, against the ~25% baseline.
It’s a good reminder that the scariest-looking corruption often has a small, boring cause — and that the way you find it is by making the failure reproducible and instrumented, not by staring harder at the panic.
The rest of it
A release this size has a long tail, but a few are worth calling out:
- A whole class of kernel panic, made impossible. A buggy or hostile program could crash the kernel by unmapping a buffer at the exact moment a blocked syscall tried to copy to it — a ring-0 page fault with no recovery. The fix is an exception table on the kernel’s user-memory copy routines (the same technique Linux uses): a fault there now returns a clean error instead of panicking. That closes the entire “validate, then block, then copy” race at the primitive, not site by site.
- Three use-after-frees and two double-frees across process exit,
/proc, pseudo-terminals,brk, andmunmap— the kind of memory-safety bugs that are individually subtle and collectively serious. - A missing futex operation (
FUTEX_REQUEUE) that had been quietly hanging every contended pthread condition variable under multi-core — a latent landmine for any real threaded program. - Filesystem fixes: two ext2 space leaks (deleting large files and truncating files both left blocks allocated), directory-entry corruption on rename and symlink, and a divide-by-zero crash on a malformed disk image.
- Networking and signals:
kill -CONT/-KILLnow actually act on a stopped process (they were no-ops), two cross-socket data leaks from shared scratch buffers, and IP/ICMP reflection hardening. - Polish: the boot chime is full-length again (it had been silently truncated to two seconds by an earlier size optimization), and the version number you see at boot, in the login banner, and in the About dialog now tracks the actual release instead of being frozen at an old one.
The capability core, ELF loader, terminal layer, USB stack, the compositor’s client protocol, and the package manager’s signature chain were all audited as part of this and came back clean — which is its own kind of result.
Where this sits
Aegis is still v1 software. The README still says, accurately, that the kernel likely contains real exploitable bugs and you should not deploy it on untrusted networks or with real secrets. This release doesn’t change that sentence — but it moves the needle on it more than any release so far.
To me, 1.5 feels like a halfway point — well past “a first release that boots and runs software,” but not yet the thing I’m actually building toward: a system where the capability model is fully demonstrable, where the kernel has had a real line-by-line security audit, where it self-hosts, and where it runs on a broad range of real hardware. That’s what a 2.0 means to me, and I’m not going to put that number on it prematurely.
So expect more in the 1.x line — quite possibly all the way up to 1.9 — each one chipping at that list, before a 2.0 is on the table. Slow is fine. Correct and provable is the point.
As always, the best way to shape where this goes is to contribute: exec/aegis.