Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752802AbbKYVzA (ORCPT ); Wed, 25 Nov 2015 16:55:00 -0500 Received: from mail.parknet.co.jp ([210.171.160.6]:54135 "EHLO mail.parknet.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751800AbbKYVy6 (ORCPT ); Wed, 25 Nov 2015 16:54:58 -0500 From: OGAWA Hirofumi To: Vegard Nossum Cc: Richard Weinberger , LKML Subject: Re: WARNING: CPU: 0 PID: 913 at fs/inode.c:275 drop_nlink+0x4b/0x50() References: <5652C676.8040207@oracle.com> <5653916C.7060601@nod.at> <56541AE8.2070704@oracle.com> Date: Thu, 26 Nov 2015 06:54:51 +0900 In-Reply-To: <56541AE8.2070704@oracle.com> (Vegard Nossum's message of "Tue, 24 Nov 2015 09:08:08 +0100") Message-ID: <87lh9l2190.fsf@mail.parknet.co.jp> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2760 Lines: 90 Vegard Nossum writes: > On 11/23/2015 11:21 PM, Richard Weinberger wrote: >> Am 23.11.2015 um 08:55 schrieb Vegard Nossum: >>> With the attached vfat disk image (fuzzed), I get the following WARNING: >>> >>> WARNING: CPU: 0 PID: 913 at fs/inode.c:275 drop_nlink+0x4b/0x50() > [...] >>> >>> To trigger it, you have to do a rename("/mnt/a/b/1", "/mnt/1"), where >>> /mnt is your mountpoint. >> >> Not here. All I get is: >> FAT-fs (ubdb): Corrupted directory (i_pos 244) >> >> Did you something before the rename()? > > No, nothing before the rename. > > Did you use mv to generate the rename()? Then you may have to do 'mv > /mnt/a/b/1 /mnt/', otherwise it ends up doing rename("/mnt/a/b/1", > "/mnt/1/1") which only shows the message you saw. Let me know if this helps. > > Thanks for having a look, Can you try this one? -- OGAWA Hirofumi [PATCH] fat: Add simple validation for directory inode This detects simple corruption cases of directory, and try to avoid further damage to user data. And performance impact of this validation should be very low, or not measurable. Signed-off-by: OGAWA Hirofumi --- fs/fat/inode.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff -puN fs/fat/inode.c~fat-validate-dir fs/fat/inode.c --- linux/fs/fat/inode.c~fat-validate-dir 2015-11-26 06:31:39.666959958 +0900 +++ linux-hirofumi/fs/fat/inode.c 2015-11-26 06:31:39.670959945 +0900 @@ -449,6 +449,24 @@ static int fat_calc_dir_size(struct inod return 0; } +static int fat_validate_dir(struct inode *dir) +{ + struct super_block *sb = dir->i_sb; + + if (dir->i_nlink < 2) { + /* Directory should have "."/".." entries at least. */ + fat_fs_error(sb, "corrupted directory (invalid entries)"); + return -EIO; + } + if (MSDOS_I(dir)->i_start == 0 || + MSDOS_I(dir)->i_start == MSDOS_SB(sb)->root_cluster) { + /* Directory should point valid cluster. */ + fat_fs_error(sb, "corrupted directory (invalid i_start)"); + return -EIO; + } + return 0; +} + /* doesn't deal with root inode */ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) { @@ -475,6 +493,10 @@ int fat_fill_inode(struct inode *inode, MSDOS_I(inode)->mmu_private = inode->i_size; set_nlink(inode, fat_subdirs(inode)); + + error = fat_validate_dir(inode); + if (error < 0) + return error; } else { /* not a directory */ inode->i_generation |= 1; inode->i_mode = fat_make_mode(sbi, de->attr, _ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/