Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b534e70cf5529378a1ed994492641ec0330554eb
Commit:     b534e70cf5529378a1ed994492641ec0330554eb
Parent:     69ca4378aa376cf2c49657d4f6951da56c27cd3a
Author:     David Woodhouse <[EMAIL PROTECTED]>
AuthorDate: Sat Oct 13 11:35:58 2007 +0100
Committer:  David Woodhouse <[EMAIL PROTECTED]>
CommitDate: Sat Oct 13 11:35:58 2007 +0100

    [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 <[EMAIL PROTECTED]>
---
 fs/jffs2/gc.c      |    7 ++++++-
 fs/jffs2/scan.c    |   15 +++++++++++----
 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 95be264..f25e485 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,
                        goto bail;
                }
 
+               if (strnlen(node->d.name, node->d.nsize) != node->d.nsize) {
+                       printk(KERN_WARNING "Name in dirent node at 0x%08x 
contains zeroes\n", ref_offset(raw));
+                       goto bail;
+               }
+
                if (node->d.nsize) {
                        crc = crc32(0, node->d.name, node->d.nsize);
                        if (je32_to_cpu(node->d.name_crc) != crc) {
-                               printk(KERN_WARNING "Name CRC failed on 
REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
+                               printk(KERN_WARNING "Name CRC failed on 
REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
                                       ref_offset(raw), 
je32_to_cpu(node->d.name_crc), crc);
                                goto bail;
                        }
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 35ef8d8..272872d 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
 {
        struct jffs2_full_dirent *fd;
        struct jffs2_inode_cache *ic;
+       uint32_t checkedlen;
        uint32_t crc;
        int err;
 
@@ -1024,12 +1025,18 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info 
*c, struct jffs2_eraseblo
 
        pseudo_random += je32_to_cpu(rd->version);
 
-       fd = jffs2_alloc_full_dirent(rd->nsize+1);
+       /* Should never happen. Did. (OLPC trac #4184)*/
+       checkedlen = strnlen(rd->name, rd->nsize);
+       if (checkedlen < rd->nsize) {
+               printk(KERN_ERR "Dirent at %08x has zeroes in name. Truncating 
to %d chars\n",
+                      ofs, checkedlen);
+       }
+       fd = jffs2_alloc_full_dirent(checkedlen+1);
        if (!fd) {
                return -ENOMEM;
        }
-       memcpy(&fd->name, rd->name, rd->nsize);
-       fd->name[rd->nsize] = 0;
+       memcpy(&fd->name, rd->name, checkedlen);
+       fd->name[checkedlen] = 0;
 
        crc = crc32(0, fd->name, rd->nsize);
        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
        fd->next = NULL;
        fd->version = je32_to_cpu(rd->version);
        fd->ino = je32_to_cpu(rd->ino);
-       fd->nhash = full_name_hash(fd->name, rd->nsize);
+       fd->nhash = full_name_hash(fd->name, checkedlen);
        fd->type = rd->type;
        jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 2a77d3f..629af01 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
 
                        case JFFS2_NODETYPE_DIRENT: {
                                struct jffs2_sum_dirent_flash *spd;
+                               int checkedlen;
                                spd = sp;
 
                                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
                                            jeb->offset + 
je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
 
 
-                               fd = jffs2_alloc_full_dirent(spd->nsize+1);
+                               /* This should never happen, but 
https://dev.laptop.org/ticket/4184 */
+                               checkedlen = strnlen(spd->name, spd->nsize);
+                               if (!checkedlen) {
+                                       printk(KERN_ERR "Dirent at %08x has 
zero at start of name. Aborting mount.\n",
+                                              jeb->offset + 
je32_to_cpu(spd->offset));
+                                       return -EIO;
+                               }
+                               if (checkedlen < spd->nsize) {
+                                       printk(KERN_ERR "Dirent at %08x has 
zeroes in name. Truncating to %d chars\n",
+                                              jeb->offset + 
je32_to_cpu(spd->offset), checkedlen);
+                               }
+
+
+                               fd = jffs2_alloc_full_dirent(checkedlen+1);
                                if (!fd)
                                        return -ENOMEM;
 
-                               memcpy(&fd->name, spd->name, spd->nsize);
-                               fd->name[spd->nsize] = 0;
+                               memcpy(&fd->name, spd->name, checkedlen);
+                               fd->name[checkedlen] = 0;
 
                                ic = jffs2_scan_make_ino_cache(c, 
je32_to_cpu(spd->pino));
                                if (!ic) {
@@ -455,7 +469,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info 
*c, struct jffs2_eras
                                fd->next = NULL;
                                fd->version = je32_to_cpu(spd->version);
                                fd->ino = je32_to_cpu(spd->ino);
-                               fd->nhash = full_name_hash(fd->name, 
spd->nsize);
+                               fd->nhash = full_name_hash(fd->name, 
checkedlen);
                                fd->type = spd->type;
 
                                jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to