Skip to content

Commit

Permalink
Fix extraction of files with size greater than one erase block.
Browse files Browse the repository at this point in the history
A regression was introduced with commit 70a2345 where we only took inode
nodes with the highest version into account when extracting files from a
JFFS2 filesystem.

When files have a size greater than 1 erase block, the file is split
into multiple JFFS2 inode nodes having the same inode (they belong to
the same file) but different versions. These files should be recreated
on disk by walking through the list of inode nodes, order by version.
Each node has an offset within the file so we simply seek in the output
file and write the node content in place.

Reference: https://sourceware.org/jffs2/jffs2-slides-transformed.pdf
  • Loading branch information
qkaiser committed Jun 23, 2022
1 parent ddbc592 commit ca31947
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/scripts/jefferson
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,9 @@ def scan_fs(content, endianness, verbose=False):
inode.unpack(content_mv[0 + offset :])

if inode.ino in fs[JFFS2_NODETYPE_INODE]:
if inode.version > fs[JFFS2_NODETYPE_INODE][inode.ino].version:
fs[JFFS2_NODETYPE_INODE][inode.ino] = inode
fs[JFFS2_NODETYPE_INODE][inode.ino].append(inode)
else:
fs[JFFS2_NODETYPE_INODE][inode.ino] = inode
fs[JFFS2_NODETYPE_INODE][inode.ino] = [inode]
if verbose:
print("0x%08X:" % (offset), inode)
elif unknown_node.nodetype == JFFS2_NODETYPE_CLEANMARKER:
Expand Down Expand Up @@ -358,15 +357,17 @@ def get_device(inode):
return os.makedev((node.old_id >> 8) & 0xFF, node.old_id & 0xFF)
return None

def sort_version(item):
return item.version

def dump_fs(fs, target):
node_dict = {}

for dirent in fs[JFFS2_NODETYPE_DIRENT].values():
dirent.inodes = []
for inode in fs[JFFS2_NODETYPE_INODE].values():
if inode.ino == dirent.ino:
dirent.inodes.append(inode)
for ino, inodes in fs[JFFS2_NODETYPE_INODE].items():
if ino == dirent.ino:
dirent.inodes = sorted(inodes, key=sort_version)
node_dict[dirent.ino] = dirent

for dirent in fs[JFFS2_NODETYPE_DIRENT].values():
Expand Down

0 comments on commit ca31947

Please sign in to comment.