All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yunlong Song <yunlong.song@huawei.com>
To: <jaegeuk@kernel.org>, <chao@kernel.org>, <yuchao0@huawei.com>,
	<yunlong.song@icloud.com>, <yunlong.song@huawei.com>
Cc: <miaoxie@huawei.com>, <bintian.wang@huawei.com>,
	<shengyong1@huawei.com>, <heyunlei@huawei.com>,
	<linux-fsdevel@vger.kernel.org>,
	<linux-f2fs-devel@lists.sourceforge.net>,
	<linux-kernel@vger.kernel.org>
Subject: [PATCH v4] fsck.f2fs: check and fix i_namelen to avoid double free
Date: Mon, 18 Dec 2017 21:25:27 +0800	[thread overview]
Message-ID: <1513603527-163036-1-git-send-email-yunlong.song@huawei.com> (raw)
In-Reply-To: <1513319130-114230-1-git-send-email-yunlong.song@huawei.com>

v1 -> v2: use child_info to pass dentry namelen
v2 -> v3: check child != NULL to include the F2FS_FT_ORPHAN file type
v3 -> v4: fix the i_namelen problem of dump.f2fs

Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
---
 fsck/fsck.c | 28 +++++++++++++++++++++++-----
 fsck/fsck.h |  3 ++-
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 2212aa3..5407cf2 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -539,7 +539,7 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
 
 		if (sanity_check_inode(sbi, node_blk))
 			goto err;
-		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni);
+		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni, child);
 		quota_add_inode_usage(fsck->qctx, nid, &node_blk->i);
 	} else {
 		switch (ntype) {
@@ -633,7 +633,7 @@ unmatched:
 /* start with valid nid and blkaddr */
 void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 		enum FILE_TYPE ftype, struct f2fs_node *node_blk,
-		u32 *blk_cnt, struct node_info *ni)
+		u32 *blk_cnt, struct node_info *ni, struct child_info *child_d)
 {
 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
 	struct child_info child;
@@ -850,8 +850,23 @@ skip_blkcnt_fix:
 	en = malloc(F2FS_NAME_LEN + 1);
 	ASSERT(en);
 
-	namelen = convert_encrypted_name(node_blk->i.i_name,
-					le32_to_cpu(node_blk->i.i_namelen),
+	namelen = le32_to_cpu(node_blk->i.i_namelen);
+	if (namelen > F2FS_NAME_LEN) {
+		if (child_d && child_d->i_namelen <= F2FS_NAME_LEN) {
+			ASSERT_MSG("ino: 0x%x has i_namelen: 0x%x, "
+					"but has %d characters for name",
+					nid, namelen, child_d->i_namelen);
+			if (c.fix_on) {
+				FIX_MSG("[0x%x] i_namelen=0x%x -> 0x%x", nid, namelen,
+					child_d->i_namelen);
+				node_blk->i.i_namelen = cpu_to_le32(child_d->i_namelen);
+				need_fix = 1;
+			}
+			namelen = child_d->i_namelen;
+		} else
+			namelen = F2FS_NAME_LEN;
+	}
+	namelen = convert_encrypted_name(node_blk->i.i_name, namelen,
 					en, file_enc_name(&node_blk->i));
 	en[namelen] = '\0';
 	if (ftype == F2FS_FT_ORPHAN)
@@ -1098,6 +1113,8 @@ int convert_encrypted_name(unsigned char *name, int len,
 				unsigned char *new, int enc_name)
 {
 	if (!enc_name) {
+		if (len > F2FS_NAME_LEN)
+			len = F2FS_NAME_LEN;
 		memcpy(new, name, len);
 		new[len] = 0;
 		return len;
@@ -1414,9 +1431,10 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child,
 				dentry, max, i, last_blk, enc_name);
 
 		blk_cnt = 1;
+		child->i_namelen = name_len;
 		ret = fsck_chk_node_blk(sbi,
 				NULL, le32_to_cpu(dentry[i].ino),
-				ftype, TYPE_INODE, &blk_cnt, NULL);
+				ftype, TYPE_INODE, &blk_cnt, child);
 
 		if (ret && c.fix_on) {
 			int j;
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 0343fbd..d635c5a 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -54,6 +54,7 @@ struct child_info {
 	u32 pp_ino;		/*parent parent ino*/
 	struct extent_info ei;
 	u32 last_blk;
+	u32 i_namelen;  /* dentry namelen */
 };
 
 struct f2fs_fsck {
@@ -128,7 +129,7 @@ extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
 		enum FILE_TYPE, enum NODE_TYPE, u32 *,
 		struct child_info *);
 extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE,
-		struct f2fs_node *, u32 *, struct node_info *);
+		struct f2fs_node *, u32 *, struct node_info *, struct child_info *);
 extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
 		u32, enum FILE_TYPE, struct f2fs_node *, u32 *,
 		struct child_info *, struct node_info *);
-- 
1.8.5.2

WARNING: multiple messages have this Message-ID (diff)
From: Yunlong Song <yunlong.song@huawei.com>
To: jaegeuk@kernel.org, chao@kernel.org, yuchao0@huawei.com,
	yunlong.song@icloud.com, yunlong.song@huawei.com
Cc: miaoxie@huawei.com, bintian.wang@huawei.com,
	shengyong1@huawei.com, heyunlei@huawei.com,
	linux-fsdevel@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org
Subject: [PATCH v4] fsck.f2fs: check and fix i_namelen to avoid double free
Date: Mon, 18 Dec 2017 21:25:27 +0800	[thread overview]
Message-ID: <1513603527-163036-1-git-send-email-yunlong.song@huawei.com> (raw)
In-Reply-To: <1513319130-114230-1-git-send-email-yunlong.song@huawei.com>

v1 -> v2: use child_info to pass dentry namelen
v2 -> v3: check child != NULL to include the F2FS_FT_ORPHAN file type
v3 -> v4: fix the i_namelen problem of dump.f2fs

Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
---
 fsck/fsck.c | 28 +++++++++++++++++++++++-----
 fsck/fsck.h |  3 ++-
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 2212aa3..5407cf2 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -539,7 +539,7 @@ int fsck_chk_node_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode,
 
 		if (sanity_check_inode(sbi, node_blk))
 			goto err;
-		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni);
+		fsck_chk_inode_blk(sbi, nid, ftype, node_blk, blk_cnt, &ni, child);
 		quota_add_inode_usage(fsck->qctx, nid, &node_blk->i);
 	} else {
 		switch (ntype) {
@@ -633,7 +633,7 @@ unmatched:
 /* start with valid nid and blkaddr */
 void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid,
 		enum FILE_TYPE ftype, struct f2fs_node *node_blk,
-		u32 *blk_cnt, struct node_info *ni)
+		u32 *blk_cnt, struct node_info *ni, struct child_info *child_d)
 {
 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
 	struct child_info child;
@@ -850,8 +850,23 @@ skip_blkcnt_fix:
 	en = malloc(F2FS_NAME_LEN + 1);
 	ASSERT(en);
 
-	namelen = convert_encrypted_name(node_blk->i.i_name,
-					le32_to_cpu(node_blk->i.i_namelen),
+	namelen = le32_to_cpu(node_blk->i.i_namelen);
+	if (namelen > F2FS_NAME_LEN) {
+		if (child_d && child_d->i_namelen <= F2FS_NAME_LEN) {
+			ASSERT_MSG("ino: 0x%x has i_namelen: 0x%x, "
+					"but has %d characters for name",
+					nid, namelen, child_d->i_namelen);
+			if (c.fix_on) {
+				FIX_MSG("[0x%x] i_namelen=0x%x -> 0x%x", nid, namelen,
+					child_d->i_namelen);
+				node_blk->i.i_namelen = cpu_to_le32(child_d->i_namelen);
+				need_fix = 1;
+			}
+			namelen = child_d->i_namelen;
+		} else
+			namelen = F2FS_NAME_LEN;
+	}
+	namelen = convert_encrypted_name(node_blk->i.i_name, namelen,
 					en, file_enc_name(&node_blk->i));
 	en[namelen] = '\0';
 	if (ftype == F2FS_FT_ORPHAN)
@@ -1098,6 +1113,8 @@ int convert_encrypted_name(unsigned char *name, int len,
 				unsigned char *new, int enc_name)
 {
 	if (!enc_name) {
+		if (len > F2FS_NAME_LEN)
+			len = F2FS_NAME_LEN;
 		memcpy(new, name, len);
 		new[len] = 0;
 		return len;
@@ -1414,9 +1431,10 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, struct child_info *child,
 				dentry, max, i, last_blk, enc_name);
 
 		blk_cnt = 1;
+		child->i_namelen = name_len;
 		ret = fsck_chk_node_blk(sbi,
 				NULL, le32_to_cpu(dentry[i].ino),
-				ftype, TYPE_INODE, &blk_cnt, NULL);
+				ftype, TYPE_INODE, &blk_cnt, child);
 
 		if (ret && c.fix_on) {
 			int j;
diff --git a/fsck/fsck.h b/fsck/fsck.h
index 0343fbd..d635c5a 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -54,6 +54,7 @@ struct child_info {
 	u32 pp_ino;		/*parent parent ino*/
 	struct extent_info ei;
 	u32 last_blk;
+	u32 i_namelen;  /* dentry namelen */
 };
 
 struct f2fs_fsck {
@@ -128,7 +129,7 @@ extern int fsck_chk_node_blk(struct f2fs_sb_info *, struct f2fs_inode *, u32,
 		enum FILE_TYPE, enum NODE_TYPE, u32 *,
 		struct child_info *);
 extern void fsck_chk_inode_blk(struct f2fs_sb_info *, u32, enum FILE_TYPE,
-		struct f2fs_node *, u32 *, struct node_info *);
+		struct f2fs_node *, u32 *, struct node_info *, struct child_info *);
 extern int fsck_chk_dnode_blk(struct f2fs_sb_info *, struct f2fs_inode *,
 		u32, enum FILE_TYPE, struct f2fs_node *, u32 *,
 		struct child_info *, struct node_info *);
-- 
1.8.5.2

  parent reply	other threads:[~2017-12-18 13:25 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-15  6:25 [PATCH] fsck.f2fs: check and fix i_namelen to avoid double free Yunlong Song
2017-12-15  6:25 ` Yunlong Song
2017-12-15 10:01 ` Sheng Yong
2017-12-15 10:01   ` Sheng Yong
2017-12-18 11:15 ` [PATCH v2] " Yunlong Song
2017-12-18 11:15   ` Yunlong Song
2017-12-18 13:10 ` [PATCH v3] " Yunlong Song
2017-12-18 13:10   ` Yunlong Song
2017-12-18 13:25 ` Yunlong Song [this message]
2017-12-18 13:25   ` [PATCH v4] " Yunlong Song
2017-12-23  3:05   ` Chao Yu
2017-12-23  3:05     ` Chao Yu
2017-12-23  3:19     ` Yunlong Song
2017-12-23  3:19       ` Yunlong Song
2017-12-23  3:35       ` Chao Yu
2017-12-23  3:35         ` Chao Yu
2017-12-23  3:40         ` Yunlong Song
2017-12-23  3:40           ` Yunlong Song

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1513603527-163036-1-git-send-email-yunlong.song@huawei.com \
    --to=yunlong.song@huawei.com \
    --cc=bintian.wang@huawei.com \
    --cc=chao@kernel.org \
    --cc=heyunlei@huawei.com \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miaoxie@huawei.com \
    --cc=shengyong1@huawei.com \
    --cc=yuchao0@huawei.com \
    --cc=yunlong.song@icloud.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.