Skip to content

sxverity: identify the SpaceX dm-verity container (#55) - #60

Merged
nmatt0 merged 1 commit into
masterfrom
feat/sxverity-container
Oct 17, 2026
Merged

nmatt0 merged 1 commit into
masterfrom
feat/sxverity-container

Conversation

@nmatt0

@nmatt0 nmatt0 commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #55. moria had no signature for the sxverity container, so on images that use it, it named only the inner romfs payload and left the 4 KiB structured header as an unnamed gap (reported neither as a finding nor, by default, as an unidentified region).

sxverity is SpaceX's wrapper around the Linux dm-verity feature, used on Starlink User Terminal firmware. The container is a 4 KiB preamble of four 1024-byte records (the ASCII magic sxverity starts each one at 0x000/0x400/0x800/0xC00), each carrying a dm-verity root hash, a public key, and an ed25519 signature; the protected payload (a big-endian romfs) follows at 0x1000. Publicly documented by Quarkslab, "Diving into Starlink's User Terminal Firmware".

Approach

Identify-only signature + validator, in the style of verity and luks (no extractor — the romfs payload is already extractable on its own). The validator confirms the four records and the romfs payload, then sizes the finding to the 4 KiB record table, so the header is named and the romfs surfaces as its own finding at 0x1000. It rejects a stray sxverity string that lacks the structure, which matters because the romfs volume name is itself sxverity. Reaches the consistent tier (magic + full record table + payload cross-check).

Notes on the format

The record's +0x0c and +0x14 fields are not fixed constants — across the two sample partitions, +0x0c is a size that ranges from 2 KiB to ~23 MB and +0x14 varies (likely verity block counts) — so the validator keys on the stable structure (four records + romfs) rather than those fields. The record body carries the root hash / public key / signature, but their slots are not cleanly aligned, so they are not surfaced as byte-level evidence here.

Results

  • On the real partitions the summary goes from romfs to sxverity, romfs, the 4 KiB header is a consistent-tier finding and no longer an unnamed gap, and the romfs is still reported and extractable at 0x1000.
  • False-positive sweep over a firmware corpus of 1127 files: 2 sxverity findings, both genuine, nothing else; 0 crashes. The 8-byte ASCII magic plus the required four-record-and-payload structure is decisive.
  • Full test suite green; ASan/UBSan clean on the real images and the synthetic fixtures.

Tests

A synthetic container fixture + MANIFEST entry (satisfies the coverage gate), and tests/test_sxverity.py: identify at offset 0 sized to the record table, the romfs payload at 0x1000, embedded-at-offset, false-positive guards (a lone magic, four records with no payload, a single record), and an opt-in round-trip against real images via $MORIA_SXVERITY_SAMPLES that self-skips when unset, so CI stays self-contained.

moria had no signature for the sxverity container, so on images that use it
it named only the inner romfs payload and left the 4 KiB structured header
as an unnamed gap (reported neither as a finding nor, by default, as an
unidentified region).

sxverity is SpaceX's wrapper around the Linux dm-verity feature, used on
Starlink User Terminal firmware. The container is a 4 KiB preamble of four
1024-byte records (the ASCII magic "sxverity" starts each one at 0x000 /
0x400 / 0x800 / 0xC00), each carrying a dm-verity root hash, a public key,
and an ed25519 signature; the protected payload (a big-endian romfs) follows
at 0x1000. Documented by Quarkslab, "Diving into Starlink's User Terminal
Firmware".

Add an identify-only signature + validator (like verity/luks; the romfs
payload is already extractable on its own). The validator confirms the four
records and the romfs payload, then sizes the finding to the 4 KiB record
table, so the header is named and the romfs surfaces as its own finding. It
rejects a stray "sxverity" string that lacks the structure, which matters
because the romfs volume name is itself "sxverity". Reaches the consistent
tier (magic + full record table + payload cross-check).

The 8-byte ASCII magic plus the required four-record-and-payload structure is
low false-positive: a sweep over a firmware corpus of 1127 files produced two
sxverity findings, both the real Starlink partitions, and nothing else.

On the real partitions the summary goes from "romfs" to "sxverity, romfs",
the 4 KiB header is a consistent-tier finding and no longer an unnamed gap,
and the romfs is still reported and extractable at 0x1000.

Note on the format: the record's +0x0c and +0x14 fields are not fixed
constants (across the two sample partitions +0x0c is a size that ranges from
2 KiB to ~23 MB and +0x14 varies, likely verity block counts), so the
validator keys on the stable structure rather than those fields. The record
body carries the root hash / public key / signature, but their slots are not
cleanly aligned, so they are not surfaced as byte-level evidence here.

Tests: a synthetic container fixture + MANIFEST entry (satisfies the coverage
gate), and tests/test_sxverity.py (identify at offset 0 sized to the record
table, the romfs payload at 0x1000, embedded-at-offset, false-positive guards
for a lone magic / missing payload / single record, and a round-trip against
the real Starlink partitions that self-skips when they are absent). Full suite
green; ASan/UBSan clean on the real partitions and the fixtures.
@nmatt0
nmatt0 merged commit 84633c6 into master Oct 17, 2026
4 checks passed
@nmatt0
nmatt0 deleted the feat/sxverity-container branch October 17, 2026 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Identify the "sxverity" container (SpaceX dm-verity wrapper): magic + 1 KiB record table, romfs payload

1 participant