Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

.erebus Format v2 — SISR extension

Status: implemented (erebus-core sisr_header + manifest modules). Specifies the .erebus layout enriched with the SISR header and the embedded delta manifest, and how it stays byte-for-byte backward compatible with existing decoders.

The stock .erebus layout [stub][payload][metadata][footer] is unchanged. SISR adds two blocks between the app metadata and the standard footer, and signals their presence with one spare bit of the footer flags byte.

Physical layout

+------------------------------------------------------------------+
| Executable Header & Embedded Runtime (ELF/PE)                    |
+------------------------------------------------------------------+
| Application Payload (SquashFS Compressed Data)                   |
+------------------------------------------------------------------+
| App metadata (JSON)                                              |
+------------------------------------------------------------------+
| Signature block (v3+, optional, unchanged)                       |
+------------------------------------------------------------------+
| SISR Section (DeltaManifest: chunk index)                       |
+------------------------------------------------------------------+
| SISR footer extension (110 bytes, fixed)                        |
+------------------------------------------------------------------+
| Standard erebus Footer (84 or 92 bytes, EREBUS_MAGIC at EOF)        |
+------------------------------------------------------------------+

Offsets within the standard footer (payload_offset, meta_offset, sig_offset) are absolute and therefore unaffected by the insertion.

Backward compatibility

  • EREBUS_MAGIC (0x5842494E + \x01) stays at the exact end of the file, and the standard footer is byte-for-byte identical with or without SISR.
  • Legacy decoders read the footer backwards from EOF; the SISR blocks sit before it and are never seen.
  • Presence is signaled by the FLAG_SISR bit (0x04) of the footer flags byte. Existing readers that only test FLAG_SIGNED / FLAG_ENCRYPTED are unaffected; a legacy file without the bit decodes transparently.
  • A new reader locates the extension at file_len - footer_size - 110, where footer_size is 84 (v2) or 92 (v3+), from Footer::footer_size().
offsetsizefieldmeaning
02sisr_versionextension schema version (1); 0 = absent
28chunk_table_offsetabsolute file offset of the DeltaManifest
104chunk_table_lenbyte length of the DeltaManifest
1432merkle_rootMerkle root over the payload chunk hashes
4664signatureEd25519 signature over merkle_root ‖ manifest

Serialized by SisrFooterExt::pack() / SisrFooterExt::parse(). The signature is computed over the concatenation of the 32-byte Merkle root and the serialized DeltaManifest, so the extension and the chunk table are bound together: any alteration of either invalidates the signature.

DeltaManifest (the SISR Section)

offsetsizefield
04magic XBMD
41version (1)
53reserved (zero)
84chunk_count
128payload_len
2036·nChunkEntry table

ChunkEntry = hash [u8; 32] + length u32, little-endian. Chunks are in payload order; each is addressed by content, so reuse and tamper detection follow from the hash. See the delta manifest format for how the chunk list drives an incremental update.

Remote manifest (<name>.erebus.manifest)

The builder writes a self-contained, signed copy of the manifest next to the binary:

| magic "XBMR" (4) | version (1) | reserved (3) | merkle_root (32) | signature (64) | DeltaManifest |

The signature is over merkle_root ‖ DeltaManifest (identical to the embedded header), so the remote file can be served over HTTPS / a package registry and verified offline without touching the .erebus. RemoteManifest::verify_signature and verify_merkle check both bindings.

Security

Strict bounds checking everywhere a hostile file could trigger OOB reads or over-allocation:

  • chunk_table_offset + chunk_table_len is checked with checked arithmetic and must end before the SISR extension (never in the footer or the extension itself).
  • The manifest buffer length must equal 20 + 36 × chunk_count exactly; count-derived sizes are computed with checked arithmetic before the chunk vector is allocated, so a forged chunk_count fails without allocating or over-reading.
  • Unknown schema versions are rejected (same rule as .erebus format versions).

Performance

Fixed overhead: 110 bytes for the extension. The manifest adds 20 + 36n bytes for n chunks. A 100-chunk app therefore adds ~3.7 KiB of SISR header metadata — under the 4 KiB budget. The extension carries the Merkle root and signature so the runtime can pre-check integrity without parsing the manifest.