Skip to content

CosmoOS 1.0.9

Choose a tag to compare

@github-actions github-actions released this 22 Oct 03:48
· 82 commits to main since this release
4527d16

If you rolled back and forward on v1.0.8: run cosmo-upgrade --repair

On v1.0.8, cosmo-upgrade --rollback to v1.0.7, then v1.0.7's own
cosmo-upgrade --rollback forward again, left the root's record of its
base system (/var/lib/cosmo-upgrade/root-set) naming v1.0.7's set.
v1.0.8 trusted that record, so it refused every later upgrade (the root holds another set's base system than the current set's (a rollback half done): cosmo-upgrade --repair first), and its --repair found nothing
to do.

On such a system, run CosmoOS 1.0.9's cosmo-upgrade --repair once,
from the release's signed package, then upgrade as usual:

cosmo$ mkdir /tmp/up && cd /tmp/up
cosmo$ wget -q https://vkuttyp.github.io/CosmoOS/releases/v1.0.9/cosmoos-x86_64-cosmo-upgrade.cpk
cosmo$ pkg install -n ./cosmoos-x86_64-cosmo-upgrade.cpk
cosmo$ tar -xf cosmoos-x86_64-cosmo-upgrade.cpk sbin/cosmo-upgrade
cosmo$ ./sbin/cosmo-upgrade --repair
cosmo-upgrade: the root's record named the previous set's (v1.0.7, ...) base system, but its files are the current set's (v1.0.8, ...): record corrected
cosmo$ cd / && cosmo-upgrade --fetch v1.0.9

(aarch64 in place of x86_64 on an ARM machine.) --repair corrects
the record from the root's files and changes nothing else. A system that
never rolled back needs none of this: cosmo-upgrade --fetch v1.0.9.

From this release on, the record is checked, not trusted. Which set's
base system the root holds is told from the root's own files: the files
each kept boot set's boot.tar puts under /bin, /sbin, /usr, /lib
and the package repository, byte for byte (/etc is yours and is not
looked at). An upgrade is refused only when those files are the previous
set's -- a rollback really half done -- never on the record alone. When
the record disagrees with the files, cosmo-upgrade --list says so and
names both, and the upgrade, a rollback and --repair correct it. The
record now also names the release it describes and the set it was
written from, so a record an older cosmo-upgrade left behind is named
as such. cosmo-install writes it at install.

Fixes

  • A long console write no longer stops a CPU's interrupts. The
    console held its lock, with interrupts off, for the whole of one write
    while every output device drew it. dmesg prints the kernel log in one
    32 KiB write; drawn on the screen console, that kept one CPU without
    interrupts for over a second, and another CPU waiting on it for a TLB
    invalidation panicked (mmu: TLB shootdown ... acknowledged by 2 of 3 CPUs). A write is now passed on a line at a time. A virtio console
    whose device stops answering still costs one 200 ms wait per write.
  • pkg says a downgrade is a downgrade. pkg install NAME=VERSION
    to an older version said NAME will be upgraded from 1.1 to 1.0; it
    says downgraded.

Upgrading from v1.0.8

cosmo-upgrade --fetch v1.0.9 (after --repair as above, if you rolled
back and forward), reboot, then pkg update && pkg upgrade. This upgrade
takes a boot environment, so cosmo-upgrade --rollback returns the root
and the boot set as they were.

Tested: on every change and on both architectures, make test-upgrade,
whose test-be now includes the published v1.0.7 upgraded to this
build, rolled back, rolled forward by v1.0.7's own cosmo-upgrade, and
upgraded again; and on a Parallels virtual machine in that state, which
--repair cleared before it upgraded to this release.

About CosmoOS

CosmoOS 1.0.9: the 1.0 roadmap completed. CosmoOS installs to a disk, reboots into it, is used through BusyBox ash, keeps files across reboots, reaches the network by name, accepts an ssh login, and has a verified boot chain and sound randomness, on x86-64 and AArch64 under QEMU.

Start with the user guide. Each architecture's files: cosmoos-ARCH.img (the signed live image), its UEFI loader, kernel.elf, boot.tar, cmdline, the signed manifest, cosmo-upgrade and its signed package. SHA256SUMS.sig is SHA256SUMS's detached signature with the release key below (scripts/modsign.py verify-detached, or cosmo-verify on an installed system); check the files with sha256sum --ignore-missing -c SHA256SUMS.

Release signing key

The loader in these images verifies the kernel, boot archive and command line against this Ed25519 key (and the kernel trusts it for modules and packages):

  • public key: d2c778bcb38775790b6b6e843631bd2e76d6a29ec52296ece6e2d67c1bef41f8
  • key id: 36ae7bb4947896ab (the first 8 bytes of SHA-512 of the key; the boot log prints it: verified boot, key 36ae7bb4947896ab)
  • in the repository: tools/keys/release-2026.pub

Toolchain

Built and tested in the project's CI images (ci/Dockerfile), pinned by digest:

  • toolchain: ghcr.io/vkuttyp/cosmoos-ci@sha256:f6aee1470b952bdb426b8d55cfcccb734c9c1f4dac50c89edefba4e8be3be385
  • litmus: ghcr.io/vkuttyp/cosmoos-ci@sha256:c8b16f9c652cd99e4a557c08adc451528cc9cd36ba0e9e37b2973feffb15a5a9
  • clang 1:19.0-63
  • lld 1:19.0-63
  • llvm 1:19.0-63
  • qemu-system-x86 1:10.0.13+ds-0+deb13u1
  • qemu-system-arm 1:10.0.13+ds-0+deb13u1
  • ovmf 2025.02-8+deb13u1
  • qemu-efi-aarch64 2025.02-8+deb13u1
  • mtools 4.0.48-1
  • python3 3.13.5-1
  • clang-19 1:19.1.7-3+b1
  • lld-19 1:19.1.7-3+b1
  • llvm-19 1:19.1.7-3+b1

Third-party sources

Fetched and checked against these SHA-256 digests (ports/busybox/busybox.mk, ports/dropbear/dropbear.mk, ports/openssh/openssh.mk, ports/mbedtls/mbedtls.mk):

Source Version SHA-256
BusyBox 1.37.0 3311dff32e746499f4df0d5df04d7eb396382d7e108bb9250e7b519b837043a4
musl 1.2.5 a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4
compiler-rt 19.1.7 c12b6e764202c615c1a3af9a13d477846878757ae0e29e5f8979215a6958fffc
dropbear 2026.94 e098034a843699200c8c977a991fff73159735bf795d5f72ef672c41a6b1ae81
OpenSSH portable (sftp-server only) 10.6p1 a9dc9565dffe8640f64d863cd29a32bc4a3dbdec0566a7fc44c5d6ee767d5f39
mbedTLS 3.6.7 a7e8bcbec0e6f761b4af24f25677626b35f762f68eef79c08677a363212d11f6
CA certificates (curl's extract of Mozilla's) 2026-09-25 a41b5d356aea97a529fe27e0f7316d2f9d946d75927476cf9cf1b90637d00505

Reproducibility

Each architecture was built twice from the tag v1.0.9, in two fresh containers of the toolchain image above, with the release key; every file below was identical in both:

  • x86_64: two builds, 10 files each, identical; cosmoos-x86_64.img sha256 fb1541a6fd72aa1d2a68cb35d87cdaacaa1b6697eccbb2315a1f8119fc4a0c34
  • aarch64: two builds, 10 files each, identical; cosmoos-aarch64.img sha256 b85c3810cfefa97c99728b3d9d9e5c72eea6652cc70f5931618a30cf5448a812

To rebuild: check out the tag, run the toolchain image above, and make ARCH=<arch> SIGNING=release MODSIGN_KEY=<key> KEYRING_PUBS=tools/keys/release-2026.pub release. Without the private key, a build with your own key differs in what the key reaches: the key ring compiled into the kernel and loader, the signatures on modules, packages and the manifest, and the archive and image that hold them.

SHA256SUMS

fb1541a6fd72aa1d2a68cb35d87cdaacaa1b6697eccbb2315a1f8119fc4a0c34  cosmoos-x86_64.img
115ef94c7916d2ba01ed3127701506beb2cc8199f6835a4e4489966fa34ffb67  cosmoos-x86_64-BOOTX64.EFI
e83d6e472bff260615596e5524a07f2aae08e239c86f33c9496828f4e0547389  cosmoos-x86_64-kernel.elf
0a0bb2f85086dd88debfadf2442950dd1ecf42c789e7919926543829547488e2  cosmoos-x86_64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14  cosmoos-x86_64-cmdline
991c47df43db1b9a0ece3dcc4ad34cb20abe6af55edf892fb2d53d3d03e53ed2  cosmoos-x86_64-manifest
341a4a4d4cb6948173b097980786019ac75b731302c4c63963441362d279cc14  cosmoos-x86_64-cosmo-upgrade
91a058c868f199c214bb2669a668f4a71336ff7014e9ea1355165f14f9a572f4  cosmoos-x86_64-cosmo-upgrade.cpk
b85c3810cfefa97c99728b3d9d9e5c72eea6652cc70f5931618a30cf5448a812  cosmoos-aarch64.img
0d00053d85654789deaf9fa0edc5cb8231d8d142140c1198bcb38cfedc8ff87e  cosmoos-aarch64-BOOTAA64.EFI
cef949411f89dde38cb888e8afb13d5125d27a975e7afa63d770782744aa9425  cosmoos-aarch64-kernel.elf
3dbb5ff80c343909a4c01c2d505c343f013e0126580c0ce54fce88ec9a7ca986  cosmoos-aarch64-boot.tar
7a77470be4312a22db40932c6cd8ddcd6d42a29b07101cbbe135cbfa1fc1aa14  cosmoos-aarch64-cmdline
7a1f112c532cfe92f7716b9991cf8db052f645a8612f9ffecf9e69e89299c878  cosmoos-aarch64-manifest
7eeaecbdce8b2a353d88848cd8a8193dc74e6f1bafde7d7ce5666aa4835f75e1  cosmoos-aarch64-cosmo-upgrade
56e8567d2276b8cc69c626f25cc141d477def973a56ba27371cc35c05353dde3  cosmoos-aarch64-cosmo-upgrade.cpk

Known limitations

What CosmoOS 1.0 does not do, or does differently from what you may
expect. Each item names where it is recorded; the work that remains
after 1.0 is in docs/plan.md, and the full list of known
gaps in the deferred-work inventory.

Machines

  • QEMU is the tested platform. x86-64 on q35 and AArch64 on virt
    are tested by CI; there is no physical hardware matrix. Since v1.0.1
    the AArch64 image boots on Parallels Desktop 27 on Apple Silicon, and
    since v1.0.3 installs on its NVMe disks and has a network there; its
    SATA disks are not seen (Tested platforms). Out of scope for 1.0
    (roadmap): GPU and display beyond a text console (on
    the firmware's framebuffer, or a virtio-gpu adapter at the display's
    own size: no 3D, cursor or display interface for programs), hotplug, NUMA, more than 64 CPUs, huge pages, live migration,
    RAID-Z, eBPF, and the Intel VMX backend on hardware.
  • Randomness from the weakest source last. The pool seeds from the
    CPU's random instructions, the firmware's EFI_RNG_PROTOCOL or a
    virtio-rng; with none of them (Parallels Desktop) a timing-jitter source
    seeds it, credited conservatively (docs/kernel/security/design.md §6).
    random.jitter=off on the command line turns that off, and the pool
    then never seeds there. The commands in this guide add -device virtio-rng-pci.
  • The clock is stepped, not slewed. The wall clock is set at boot
    from the RTC or, with none (Parallels), the firmware's time. Since
    v1.0.4 root can set it (date -s, hwclock -w where there is an RTC)
    and ntpd -q steps it once from a server; there is no NTP daemon,
    because adjtimex is not implemented, and no time zone.
  • No Wi-Fi, Bluetooth or sound.

Boot and security

  • Verified boot covers the loader's three files (kernel, boot archive,
    command line). The root filesystem is not verified; the loader is
    not signed for UEFI Secure Boot; there is no TPM measurement
    and no rollback protection for manifests or modules (inventory
    2.9).
  • No KASLR: the kernel is at a fixed address. User-space ASLR covers
    the stack, heap, mmap and PIE executables; a non-PIE (ET_EXEC)
    program loads at its fixed address.
  • One user, root. Privileges, not uids, separate what processes may
    do (Privileges). A root session holding fewer
    privileges can still rewrite files in /etc that a later boot runs
    with all of them (M5 report, inventory 2.9).

Shell and commands

  • The commands are the BusyBox applets listed in the shell
    page
    : no ping6; no hard links; no /sys.
  • /proc has the process directories and a fixed set of system files
    (meminfo, stat, loadavg, uptime, mounts, version,
    cpuinfo). A process has no nice value and no user/system split of its
    CPU time; ps's TT column is a pair of Linux device numbers (5,1
    for the console), since devices here have none of their own; and a
    process's environ is what exec gave it, not what it has since written
    over (inventory §13).
  • The terminal driver honours the common modes (canonical input, echo,
    signals, raw mode, window size); most other termios flags and control
    characters are accepted and ignored (inventory 1.4).
  • No swap.

Networking

  • wget's certificate authorities are fixed in the image
    (/etc/ssl/certs/ca-certificates.crt, as built); nothing updates them,
    and there is no certificate revocation check
    (Networking).
  • The address comes from DHCP. There is no runtime tool to set one by
    hand; /etc/resolv.conf is written once per boot, not on lease
    renewal; the DHCP client does no ARP probe or DECLINE, no INIT-REBOOT,
    no RELEASE, and ignores classless routes (option 121) (inventory 2.5).
  • IPv6 is link-local; there is no IPv6 routing beyond the link, no IP
    fragmentation, and no TCP SACK, window scaling or timestamps
    (inventory 2.5).
  • ssh is dropbear with key login only (Ed25519 or RSA), root only;
    no port forwarding (ssh).

Storage

  • cosmofs files are capped at 516128 blocks of 4 KiB (about 1.97 GiB),
    64516 blocks (252 MiB) when encrypted; a larger write fails with
    EFBIG.
  • A read-only mount still writes the replay of an interrupted free or
    orphan record, as a journalling filesystem replays its journal.
  • A rollback to a snapshot takes effect at the next boot (or the next
    mount of another filesystem), not in the running system
    (Snapshots and rollback); a clone of a clone, and a
    snapshot of a clone, are not possible; no RAID-Z, no resilvering
    (backlog CFS-9, CFS-13).
  • A root disk that appears late (USB storage) is not waited for: init
    stays on the live root and says so.

Packages

  • A network repository is fetched whole, file by file: no mirrors, no
    delta updates. Its index's freshness is only as good as the clock, which
    is stepped by hand or by ntpd -q, with no NTP daemon
    (Packages).
  • cosmo-upgrade --rollback returns packages and /etc only to a boot
    environment, which upgrades made by v1.0.8's cosmo-upgrade and later
    take; past an upgrade made by v1.0.7 or older it returns the boot set and
    the base system only (Upgrading). Only
    files under /root, /home and /var/log written after the upgrade
    are kept across a rollback; the root is rolled back at the next boot,
    never while it runs; one pool.

Linux programs

  • Static and PIE Linux binaries for x86-64 and AArch64 run under the
    Linux personality; it is a subset of Linux's system calls, so a
    program that needs a missing one gets ENOSYS. Dynamically linked
    musl programs run through musl's own linker, /lib/ld-musl-$ARCH.so.1,
    with libc.so and dlopen; glibc's has not been
    tried. A library with text relocations is refused (W^X); build it
    -fPIC. Native CosmoOS programs stay static.
    No containers or desktop software (docs/plan.md).