Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b534e70c authored by David Woodhouse's avatar David Woodhouse
Browse files

[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: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 69ca4378
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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;
			}
+11 −4
Original line number Diff line number Diff line
@@ -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);

+18 −4
Original line number Diff line number Diff line
@@ -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);