[PATCH 1/2] JFFS2: Process obsolete nodes as well as accurate ones

petr.borsodi at i.cz petr.borsodi at i.cz
Mon Apr 27 18:43:25 CEST 2020


From: Petr Borsodi <petr.borsodi at i.cz>

Obsolete nodes (ie. without the JFFS2_NODE_ACCURATE flag) were ignored because
they had seemingly invalid crc. This could lead to finding the phantom node
header in obsolete node data.

Signed-off-by: Petr Borsodi <petr.borsodi at i.cz>
---

 fs/jffs2/jffs2_1pass.c | 67 +++++++++++++++++++++++++++---------------
 1 file changed, 43 insertions(+), 24 deletions(-)

diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index 5912cde838..819a44eeeb 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -1471,7 +1471,7 @@ static u32
 jffs2_1pass_build_lists(struct part_info * part)
 {
 	struct b_lists *pL;
-	struct jffs2_unknown_node *node;
+	union jffs2_node_union *node;
 	u32 nr_sectors;
 	u32 i;
 	u32 counter4 = 0;
@@ -1507,6 +1507,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 #endif
 		/* Indicates a sector with a CLEANMARKER was found */
 		int clean_sector = 0;
+		struct jffs2_unknown_node crcnode;
 
 		/* Set buf_size to maximum length */
 		buf_size = DEFAULT_EMPTY_SCAN_SIZE;
@@ -1600,9 +1601,9 @@ jffs2_1pass_build_lists(struct part_info * part)
 			}
 			prevofs = ofs;
 			if (sector_ofs + part->sector_size <
-					ofs + sizeof(*node))
+					ofs + sizeof(struct jffs2_unknown_node))
 				break;
-			if (buf_ofs + buf_len < ofs + sizeof(*node)) {
+			if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_unknown_node)) {
 				buf_len = min_t(uint32_t, buf_size, sector_ofs
 						+ part->sector_size - ofs);
 				get_fl_mem((u32)part->offset + ofs, buf_len,
@@ -1610,7 +1611,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 				buf_ofs = ofs;
 			}
 
-			node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs];
+			node = (union jffs2_node_union *)&buf[ofs-buf_ofs];
 
 			if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
 				uint32_t inbuf_ofs;
@@ -1665,23 +1666,41 @@ jffs2_1pass_build_lists(struct part_info * part)
 			 * the 'clean_sector' flag.
 			 */
 			clean_sector = 0;
-			if (node->magic != JFFS2_MAGIC_BITMASK ||
-					!hdr_crc(node)) {
+			if (node->u.magic != JFFS2_MAGIC_BITMASK) {
+				ofs += 4;
+				counter4++;
+				continue;
+			}
+
+			crcnode.magic = node->u.magic;
+			crcnode.nodetype = node->u.nodetype | JFFS2_NODE_ACCURATE;
+			crcnode.totlen = node->u.totlen;
+			crcnode.hdr_crc = node->u.hdr_crc;
+			if (!hdr_crc(&crcnode)) {
 				ofs += 4;
 				counter4++;
 				continue;
 			}
-			if (ofs + node->totlen >
-					sector_ofs + part->sector_size) {
+
+			if (ofs + node->u.totlen > sector_ofs + part->sector_size) {
 				ofs += 4;
 				counter4++;
 				continue;
 			}
+
+			if (!(node->u.nodetype & JFFS2_NODE_ACCURATE)) {
+				DEBUGF("Obsolete node type: %x len %d offset 0x%x\n",
+					node->u.nodetype,
+					node->u.totlen, ofs);
+				ofs += ((node->u.totlen + 3) & ~3);
+				counterF++;
+				continue;
+			}
+
 			/* if its a fragment add it */
-			switch (node->nodetype) {
+			switch (node->u.nodetype) {
 			case JFFS2_NODETYPE_INODE:
-				if (buf_ofs + buf_len < ofs + sizeof(struct
-							jffs2_raw_inode)) {
+				if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) {
 					buf_len = min_t(uint32_t,
 							sizeof(struct jffs2_raw_inode),
 							sector_ofs +
@@ -1701,8 +1720,8 @@ jffs2_1pass_build_lists(struct part_info * part)
 					jffs2_free_cache(part);
 					return 0;
 				}
-				if (max_totlen < node->totlen)
-					max_totlen = node->totlen;
+				if (max_totlen < node->u.totlen)
+					max_totlen = node->u.totlen;
 				break;
 			case JFFS2_NODETYPE_DIRENT:
 				if (buf_ofs + buf_len < ofs + sizeof(struct
@@ -1711,7 +1730,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 							 jffs2_raw_dirent *)
 							node)->nsize) {
 					buf_len = min_t(uint32_t,
-							node->totlen,
+							node->u.totlen,
 							sector_ofs +
 							part->sector_size -
 							ofs);
@@ -1736,17 +1755,17 @@ jffs2_1pass_build_lists(struct part_info * part)
 					jffs2_free_cache(part);
 					return 0;
 				}
-				if (max_totlen < node->totlen)
-					max_totlen = node->totlen;
+				if (max_totlen < node->u.totlen)
+					max_totlen = node->u.totlen;
 				counterN++;
 				break;
 			case JFFS2_NODETYPE_CLEANMARKER:
-				if (node->totlen != sizeof(struct jffs2_unknown_node))
+				if (node->u.totlen != sizeof(struct jffs2_unknown_node))
 					printf("OOPS Cleanmarker has bad size "
 						"%d != %zu\n",
-						node->totlen,
+						node->u.totlen,
 						sizeof(struct jffs2_unknown_node));
-				if ((node->totlen ==
+				if ((node->u.totlen ==
 				     sizeof(struct jffs2_unknown_node)) &&
 				    (ofs == sector_ofs)) {
 					/*
@@ -1758,20 +1777,20 @@ jffs2_1pass_build_lists(struct part_info * part)
 				}
 				break;
 			case JFFS2_NODETYPE_PADDING:
-				if (node->totlen < sizeof(struct jffs2_unknown_node))
+				if (node->u.totlen < sizeof(struct jffs2_unknown_node))
 					printf("OOPS Padding has bad size "
 						"%d < %zu\n",
-						node->totlen,
+						node->u.totlen,
 						sizeof(struct jffs2_unknown_node));
 				break;
 			case JFFS2_NODETYPE_SUMMARY:
 				break;
 			default:
 				printf("Unknown node type: %x len %d offset 0x%x\n",
-					node->nodetype,
-					node->totlen, ofs);
+					node->u.nodetype,
+					node->u.totlen, ofs);
 			}
-			ofs += ((node->totlen + 3) & ~3);
+			ofs += ((node->u.totlen + 3) & ~3);
 			counterF++;
 		}
 	}
-- 
2.20.1



More information about the U-Boot mailing list