Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759555AbdLRNZs (ORCPT ); Mon, 18 Dec 2017 08:25:48 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:56260 "EHLO huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1758908AbdLRNZp (ORCPT ); Mon, 18 Dec 2017 08:25:45 -0500 From: Yunlong Song To: , , , , CC: , , , , , , Subject: [PATCH v4] fsck.f2fs: check and fix i_namelen to avoid double free Date: Mon, 18 Dec 2017 21:25:27 +0800 Message-ID: <1513603527-163036-1-git-send-email-yunlong.song@huawei.com> X-Mailer: git-send-email 1.8.5.2 In-Reply-To: <1513319130-114230-1-git-send-email-yunlong.song@huawei.com> References: <1513319130-114230-1-git-send-email-yunlong.song@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.193.250] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3542 Lines: 102 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 --- 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