diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-10-13 06:35:58 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-10-13 06:35:58 -0400 |
commit | b534e70cf5529378a1ed994492641ec0330554eb (patch) | |
tree | d0257ffa39a331cad12e855122cb1e540b0eac41 /fs | |
parent | 69ca4378aa376cf2c49657d4f6951da56c27cd3a (diff) |
[JFFS2] Handle dirents on the flash with embedded zero bytes in names.
In three places: summary scan, normal scan, REF_PRISTINE GC.
Just truncate at the NUL, since that was the correct thing to do in the
only case where this (inexplicable) breakage has been seen.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/gc.c | 7 | ||||
-rw-r--r-- | fs/jffs2/scan.c | 15 | ||||
-rw-r--r-- | fs/jffs2/summary.c | 22 |
3 files changed, 35 insertions, 9 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 95be264fe9b6..f25e485ed879 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -608,10 +608,15 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
608 | goto bail; | 608 | goto bail; |
609 | } | 609 | } |
610 | 610 | ||
611 | if (strnlen(node->d.name, node->d.nsize) != node->d.nsize) { | ||
612 | printk(KERN_WARNING "Name in dirent node at 0x%08x contains zeroes\n", ref_offset(raw)); | ||
613 | goto bail; | ||
614 | } | ||
615 | |||
611 | if (node->d.nsize) { | 616 | if (node->d.nsize) { |
612 | crc = crc32(0, node->d.name, node->d.nsize); | 617 | crc = crc32(0, node->d.name, node->d.nsize); |
613 | if (je32_to_cpu(node->d.name_crc) != crc) { | 618 | if (je32_to_cpu(node->d.name_crc) != crc) { |
614 | printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n", | 619 | printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", |
615 | ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); | 620 | ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); |
616 | goto bail; | 621 | goto bail; |
617 | } | 622 | } |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 35ef8d83366f..272872d27fd5 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -1004,6 +1004,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
1004 | { | 1004 | { |
1005 | struct jffs2_full_dirent *fd; | 1005 | struct jffs2_full_dirent *fd; |
1006 | struct jffs2_inode_cache *ic; | 1006 | struct jffs2_inode_cache *ic; |
1007 | uint32_t checkedlen; | ||
1007 | uint32_t crc; | 1008 | uint32_t crc; |
1008 | int err; | 1009 | int err; |
1009 | 1010 | ||
@@ -1024,12 +1025,18 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
1024 | 1025 | ||
1025 | pseudo_random += je32_to_cpu(rd->version); | 1026 | pseudo_random += je32_to_cpu(rd->version); |
1026 | 1027 | ||
1027 | fd = jffs2_alloc_full_dirent(rd->nsize+1); | 1028 | /* Should never happen. Did. (OLPC trac #4184)*/ |
1029 | checkedlen = strnlen(rd->name, rd->nsize); | ||
1030 | if (checkedlen < rd->nsize) { | ||
1031 | printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars\n", | ||
1032 | ofs, checkedlen); | ||
1033 | } | ||
1034 | fd = jffs2_alloc_full_dirent(checkedlen+1); | ||
1028 | if (!fd) { | 1035 | if (!fd) { |
1029 | return -ENOMEM; | 1036 | return -ENOMEM; |
1030 | } | 1037 | } |
1031 | memcpy(&fd->name, rd->name, rd->nsize); | 1038 | memcpy(&fd->name, rd->name, checkedlen); |
1032 | fd->name[rd->nsize] = 0; | 1039 | fd->name[checkedlen] = 0; |
1033 | 1040 | ||
1034 | crc = crc32(0, fd->name, rd->nsize); | 1041 | crc = crc32(0, fd->name, rd->nsize); |
1035 | if (crc != je32_to_cpu(rd->name_crc)) { | 1042 | if (crc != je32_to_cpu(rd->name_crc)) { |
@@ -1055,7 +1062,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
1055 | fd->next = NULL; | 1062 | fd->next = NULL; |
1056 | fd->version = je32_to_cpu(rd->version); | 1063 | fd->version = je32_to_cpu(rd->version); |
1057 | fd->ino = je32_to_cpu(rd->ino); | 1064 | fd->ino = je32_to_cpu(rd->ino); |
1058 | fd->nhash = full_name_hash(fd->name, rd->nsize); | 1065 | fd->nhash = full_name_hash(fd->name, checkedlen); |
1059 | fd->type = rd->type; | 1066 | fd->type = rd->type; |
1060 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); | 1067 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); |
1061 | 1068 | ||
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 2a77d3f93029..629af01e5ade 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
@@ -429,6 +429,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
429 | 429 | ||
430 | case JFFS2_NODETYPE_DIRENT: { | 430 | case JFFS2_NODETYPE_DIRENT: { |
431 | struct jffs2_sum_dirent_flash *spd; | 431 | struct jffs2_sum_dirent_flash *spd; |
432 | int checkedlen; | ||
432 | spd = sp; | 433 | spd = sp; |
433 | 434 | ||
434 | dbg_summary("Dirent at 0x%08x-0x%08x\n", | 435 | dbg_summary("Dirent at 0x%08x-0x%08x\n", |
@@ -436,12 +437,25 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
436 | jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen)); | 437 | jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen)); |
437 | 438 | ||
438 | 439 | ||
439 | fd = jffs2_alloc_full_dirent(spd->nsize+1); | 440 | /* This should never happen, but https://dev.laptop.org/ticket/4184 */ |
441 | checkedlen = strnlen(spd->name, spd->nsize); | ||
442 | if (!checkedlen) { | ||
443 | printk(KERN_ERR "Dirent at %08x has zero at start of name. Aborting mount.\n", | ||
444 | jeb->offset + je32_to_cpu(spd->offset)); | ||
445 | return -EIO; | ||
446 | } | ||
447 | if (checkedlen < spd->nsize) { | ||
448 | printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating to %d chars\n", | ||
449 | jeb->offset + je32_to_cpu(spd->offset), checkedlen); | ||
450 | } | ||
451 | |||
452 | |||
453 | fd = jffs2_alloc_full_dirent(checkedlen+1); | ||
440 | if (!fd) | 454 | if (!fd) |
441 | return -ENOMEM; | 455 | return -ENOMEM; |
442 | 456 | ||
443 | memcpy(&fd->name, spd->name, spd->nsize); | 457 | memcpy(&fd->name, spd->name, checkedlen); |
444 | fd->name[spd->nsize] = 0; | 458 | fd->name[checkedlen] = 0; |
445 | 459 | ||
446 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); | 460 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); |
447 | if (!ic) { | 461 | if (!ic) { |
@@ -455,7 +469,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
455 | fd->next = NULL; | 469 | fd->next = NULL; |
456 | fd->version = je32_to_cpu(spd->version); | 470 | fd->version = je32_to_cpu(spd->version); |
457 | fd->ino = je32_to_cpu(spd->ino); | 471 | fd->ino = je32_to_cpu(spd->ino); |
458 | fd->nhash = full_name_hash(fd->name, spd->nsize); | 472 | fd->nhash = full_name_hash(fd->name, checkedlen); |
459 | fd->type = spd->type; | 473 | fd->type = spd->type; |
460 | 474 | ||
461 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); | 475 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); |