From ca31947c4f639b93f4ae398ab825661710f3c94b Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 23 Jun 2022 08:27:54 +0200 Subject: [PATCH 1/2] Fix extraction of files with size greater than one erase block. 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 --- src/scripts/jefferson | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/scripts/jefferson b/src/scripts/jefferson index 0a6921d..25e781e 100755 --- a/src/scripts/jefferson +++ b/src/scripts/jefferson @@ -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: @@ -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(): From 5d8e2f0b2f4e6d0999382614f37981d6ca6c3d9f Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Thu, 23 Jun 2022 08:34:52 +0200 Subject: [PATCH 2/2] bump version to 0.4 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 60c30ba..232775b 100755 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from distutils.core import setup -version = "0.3" +version = "0.4" setup( name="jefferson",