summary refs log tree commit diff
path: root/fs/jffs2
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-10-13 11:35:58 +0100
committerDavid Woodhouse <dwmw2@infradead.org>2007-10-13 11:35:58 +0100
commitb534e70cf5529378a1ed994492641ec0330554eb (patch)
treed0257ffa39a331cad12e855122cb1e540b0eac41 /fs/jffs2
parent69ca4378aa376cf2c49657d4f6951da56c27cd3a (diff)
downloadlinux-b534e70cf5529378a1ed994492641ec0330554eb.tar.gz
[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/jffs2')
-rw-r--r--fs/jffs2/gc.c7
-rw-r--r--fs/jffs2/scan.c15
-rw-r--r--fs/jffs2/summary.c22
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,
 			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 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
 {
 	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 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
 
 			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);