aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-06-17 19:05:26 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-06-17 19:05:26 -0400
commit3877f0b6c9f54d43e55e532404a935b90393b635 (patch)
treeb22e658ee19ea83c630c6464ed9c7a46d8073606
parent21c8db9eff95260e543535dfc6f27164c4c0c0ff (diff)
[JFFS2] Don't trust node headers before the CRC is checked.
Especially when summary code is used, we can have in-memory data structures referencing certain nodes without them actually being readable on the flash. Discard the nodes gracefully in that case, rather than triggering a BUG(). Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--fs/jffs2/readinode.c62
1 files changed, 34 insertions, 28 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index e1acce8fb2b..5351b34d541 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -343,7 +343,7 @@ free_out:
343 * Helper function for jffs2_get_inode_nodes(). 343 * Helper function for jffs2_get_inode_nodes().
344 * It is called every time an unknown node is found. 344 * It is called every time an unknown node is found.
345 * 345 *
346 * Returns: 0 on succes; 346 * Returns: 0 on success;
347 * 1 if the node should be marked obsolete; 347 * 1 if the node should be marked obsolete;
348 * negative error code on failure. 348 * negative error code on failure.
349 */ 349 */
@@ -354,37 +354,30 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
354 354
355 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); 355 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
356 356
357 if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { 357 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
358 /* Hmmm. This should have been caught at scan time. */
359 JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
360 jffs2_dbg_dump_node(c, ref_offset(ref));
361 return 1;
362 } else {
363 switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
364 358
365 case JFFS2_FEATURE_INCOMPAT: 359 case JFFS2_FEATURE_INCOMPAT:
366 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", 360 JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
367 je16_to_cpu(un->nodetype), ref_offset(ref)); 361 je16_to_cpu(un->nodetype), ref_offset(ref));
368 /* EEP */ 362 /* EEP */
369 BUG(); 363 BUG();
370 break; 364 break;
371 365
372 case JFFS2_FEATURE_ROCOMPAT: 366 case JFFS2_FEATURE_ROCOMPAT:
373 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", 367 JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
374 je16_to_cpu(un->nodetype), ref_offset(ref)); 368 je16_to_cpu(un->nodetype), ref_offset(ref));
375 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); 369 BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
376 break; 370 break;
377 371
378 case JFFS2_FEATURE_RWCOMPAT_COPY: 372 case JFFS2_FEATURE_RWCOMPAT_COPY:
379 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", 373 JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
380 je16_to_cpu(un->nodetype), ref_offset(ref)); 374 je16_to_cpu(un->nodetype), ref_offset(ref));
381 break; 375 break;
382 376
383 case JFFS2_FEATURE_RWCOMPAT_DELETE: 377 case JFFS2_FEATURE_RWCOMPAT_DELETE:
384 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 378 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
385 je16_to_cpu(un->nodetype), ref_offset(ref)); 379 je16_to_cpu(un->nodetype), ref_offset(ref));
386 return 1; 380 return 1;
387 }
388 } 381 }
389 382
390 return 0; 383 return 0;
@@ -549,6 +542,18 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
549 542
550 node = (union jffs2_node_union *)bufstart; 543 node = (union jffs2_node_union *)bufstart;
551 544
545 /* No need to mask in the valid bit; it shouldn't be invalid */
546 if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
547 JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
548 ref_offset(ref), je16_to_cpu(node->u.magic),
549 je16_to_cpu(node->u.nodetype),
550 je32_to_cpu(node->u.totlen),
551 je32_to_cpu(node->u.hdr_crc));
552 jffs2_dbg_dump_node(c, ref_offset(ref));
553 jffs2_mark_node_obsolete(c, ref);
554 goto cont;
555 }
556
552 switch (je16_to_cpu(node->u.nodetype)) { 557 switch (je16_to_cpu(node->u.nodetype)) {
553 558
554 case JFFS2_NODETYPE_DIRENT: 559 case JFFS2_NODETYPE_DIRENT:
@@ -606,6 +611,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
606 goto free_out; 611 goto free_out;
607 612
608 } 613 }
614 cont:
609 spin_lock(&c->erase_completion_lock); 615 spin_lock(&c->erase_completion_lock);
610 } 616 }
611 617