Skip to content

dissect.jffs parser fails on NAND flash images (OOB-unaware and 0xFF padding) #20

@twiggler

Description

@twiggler

*Description:*

The dissect.jffs parser appears to be implemented to support only NOR flash or "clean" filesystem images (e.g., from mkfs.jffs2). It fails to parse raw or "cleaned" dumps from NAND flash memory for several fundamental reasons.

This makes the parser unusable for forensics on most modern embedded devices, which primarily use NAND flash.

*Issue 1 (Blocking): Parser Fails on 0xFF Padding*

The most immediate bug is that the parser's scanning logic in _scan cannot handle empty flash space, which is represented by 0xFF bytes.

On a "clean" NAND image (created with nanddump -n), the first CLEANMARKER node (which is normally at offset 0) is stripped because it was stored in the Out-of-Band (OOB) area. This means the image file itself starts with 0xFFFFFFFF....

The parser fails immediately:

It reads the first 4 bytes (0xFFFFFFFF) at offset 0.

if (node := c_jffs2.jffs2_unknown_node(fh)).magic not in JFFS2_MAGIC_NUMBERS:
raise Error(f"Unknown JFFS2 magic: {node.magic:#x}")

node.magic becomes 0xFFFF. If this is not in JFFS2_MAGIC_NUMBERS, the parser (correctly) raises an "Unknown magic" error.

If 0xFFFF is in the magic list (e.g., as JFFS2_EMPTY_BITMASK), the parser continues, but nodetype is also 0xFFFF.

It then falls into the else block:

else:
log.warning("Unknown nodetype %#x, skipping", nodetype)
totlen = int.from_bytes(fh.read(4), "little")

It reads the next 4 bytes (also 0xFFFFFFFF) and interprets totlen as 4,294,967,295.

The parser then tries to seek (totlen + 3) & ~3 bytes forward, effectively crashing the scan.

Recommendation: The _scan function must be modified to explicitly check for 0xFFFFFFFF (empty padding) and, if found, skip 4 bytes and continue scanning.

*Issue 2: Parser is Fundamentally "OOB-Unaware"*

The root cause of Issue 1 is that JFFS2 on NAND behaves differently than on NOR.

On NAND, JFFS2 stores certain critical nodes, most importantly JFFS2_NODETYPE_CLEANMARKER (e.g., nodetype 8195), exclusively in the Out-of-Band (OOB) data area.

The current parser is a simple, linear scanner. It has no concept of an interleaved OOB data stream.

This creates a "Catch-22":

If the parser is given a raw NAND dump (data+OOB interleaved), it will fail when it hits the first OOB block, which is not a valid JFFS2 node.

If the parser is given a "clean" NAND dump (created with nanddump -n to strip OOB), it fails because all CLEANMARKER nodes have been stripped, and the file begins with 0xFF padding (see Issue 1).

Recommendation: For true NAND support, the parser would need to be refactored to read a raw image and parse a separate OOB stream. At a minimum, it must be fixed to handle the "clean" dump by correctly skipping 0xFF padding (Issue 1).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions