From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB32739B949 for ; Sat, 28 Feb 2026 18:16:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772302563; cv=none; b=H2JXz7SdpantGH2JYH/mUCBdfNgejI9xrDc/I9r2nSKwo0QtCP28xiPbfSow6fBcVMjgwKedxC1ZyI4az1q+XAOdlUtBJa6Q5yWiQ517WA2gAh/gP2cZI5caSJr7KRodllku9aOHuIxUqgwNaoSv3Nsees9B0qkYcq1lb7S/PIc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772302563; c=relaxed/simple; bh=k5MFIOlgKUPvdOZRD2GgQPUooEo8w0tFdIu8d+3/gcw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XyWHVUEAvD0HpAot/bAFrVzBeGSZfNoNc1ko5UETUYZi3Z0ysJhztaEfWZkNf/XLCo6CdTHrdKv4wGEbSq28u4QAgsL40pXAfrjeATlXp6e1x0K9xFSr1chSI/7jSy+ZdsscU4YR11/VZSURpNATucxfPOB68SdNjS5xVSOJl+Y= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UkyoZ5xm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UkyoZ5xm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C7BFBC2BCAF; Sat, 28 Feb 2026 18:16:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772302563; bh=k5MFIOlgKUPvdOZRD2GgQPUooEo8w0tFdIu8d+3/gcw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UkyoZ5xmjWrte++j0OZcVW8d5BffppGSOfBBIVJwcNylqlogDNp7bDgdUW16dCTYV ln4+M0Aoi04KeXEo9zKZ5kwIqv0dsvXErLTdDnccOwml2wfSBwOlifeidL4VM2bf2w JKVslLJk7Y6NiOR49FYzs1/InKya4MenJVk9VCZS0YDljVYJPabKhplpBhkU70UT3l sGZkRfH+Q6/Y6t+6Fin79JjOhlvrNALe1ujRcBWaTSDs7AzBLmMKbp/PNWqTE3Lizo kOd7E6/QdXUbov99Y9CjAchA18fEl/sZUYJHL4sTUt2zydHLBP5XEJi/Wy6nJANp6F 9TD6EtemvDuUQ== From: Sasha Levin To: patches@lists.linux.dev Cc: Zhiyu Zhang , OGAWA Hirofumi , Al Viro , Christian Brauner , Jan Kara , Andrew Morton , Sasha Levin Subject: [PATCH 5.15 069/164] fat: avoid parent link count underflow in rmdir Date: Sat, 28 Feb 2026 13:13:28 -0500 Message-ID: <20260228181505.1600663-69-sashal@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260228181505.1600663-1-sashal@kernel.org> References: <20260228181505.1600663-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit From: Zhiyu Zhang [ Upstream commit 8cafcb881364af5ef3a8b9fed4db254054033d8a ] Corrupted FAT images can leave a directory inode with an incorrect i_nlink (e.g. 2 even though subdirectories exist). rmdir then unconditionally calls drop_nlink(dir) and can drive i_nlink to 0, triggering the WARN_ON in drop_nlink(). Add a sanity check in vfat_rmdir() and msdos_rmdir(): only drop the parent link count when it is at least 3, otherwise report a filesystem error. Link: https://lkml.kernel.org/r/20260101111148.1437-1-zhiyuzhang999@gmail.com Fixes: 9a53c3a783c2 ("[PATCH] r/o bind mounts: unlink: monitor i_nlink") Signed-off-by: Zhiyu Zhang Reported-by: Zhiyu Zhang Closes: https://lore.kernel.org/linux-fsdevel/aVN06OKsKxZe6-Kv@casper.infradead.org/T/#t Tested-by: Zhiyu Zhang Acked-by: OGAWA Hirofumi Cc: Al Viro Cc: Christian Brauner Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Sasha Levin --- fs/fat/namei_msdos.c | 7 ++++++- fs/fat/namei_vfat.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index efba301d68aec..fba3a07d39478 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c @@ -325,7 +325,12 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) err = fat_remove_entries(dir, &sinfo); /* and releases bh */ if (err) goto out; - drop_nlink(dir); + if (dir->i_nlink >= 3) + drop_nlink(dir); + else { + fat_fs_error(sb, "parent dir link count too low (%u)", + dir->i_nlink); + } clear_nlink(inode); fat_truncate_time(inode, NULL, S_CTIME); diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index e69e2a4f99b92..d8e328e390d6b 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -808,7 +808,12 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry) err = fat_remove_entries(dir, &sinfo); /* and releases bh */ if (err) goto out; - drop_nlink(dir); + if (dir->i_nlink >= 3) + drop_nlink(dir); + else { + fat_fs_error(sb, "parent dir link count too low (%u)", + dir->i_nlink); + } clear_nlink(inode); fat_truncate_time(inode, NULL, S_ATIME|S_MTIME); -- 2.51.0