| From 466087ee104fca6ea46947e5919f99a1dabbcb44 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jul 2025 10:40:16 -0700 |
| Subject: fs/ntfs3: reject index allocation if $BITMAP is empty but blocks |
| exist |
| |
| From: Moon Hee Lee <moonhee.lee.ca@gmail.com> |
| |
| [ Upstream commit 0dc7117da8f92dd5fe077d712a756eccbe377d40 ] |
| |
| Index allocation requires at least one bit in the $BITMAP attribute to |
| track usage of index entries. If the bitmap is empty while index blocks |
| are already present, this reflects on-disk corruption. |
| |
| syzbot triggered this condition using a malformed NTFS image. During a |
| rename() operation involving a long filename (which spans multiple |
| index entries), the empty bitmap allowed the name to be added without |
| valid tracking. Subsequent deletion of the original entry failed with |
| -ENOENT, due to unexpected index state. |
| |
| Reject such cases by verifying that the bitmap is not empty when index |
| blocks exist. |
| |
| Reported-by: syzbot+b0373017f711c06ada64@syzkaller.appspotmail.com |
| Closes: https://syzkaller.appspot.com/bug?extid=b0373017f711c06ada64 |
| Fixes: d99208b91933 ("fs/ntfs3: cancle set bad inode after removing name fails") |
| Tested-by: syzbot+b0373017f711c06ada64@syzkaller.appspotmail.com |
| Signed-off-by: Moon Hee Lee <moonhee.lee.ca@gmail.com> |
| Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/ntfs3/index.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c |
| index 1bf2a6593dec6..6d1bf890929d9 100644 |
| --- a/fs/ntfs3/index.c |
| +++ b/fs/ntfs3/index.c |
| @@ -1508,6 +1508,16 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, |
| bmp_size = bmp_size_v = le32_to_cpu(bmp->res.data_size); |
| } |
| |
| + /* |
| + * Index blocks exist, but $BITMAP has zero valid bits. |
| + * This implies an on-disk corruption and must be rejected. |
| + */ |
| + if (in->name == I30_NAME && |
| + unlikely(bmp_size_v == 0 && indx->alloc_run.count)) { |
| + err = -EINVAL; |
| + goto out1; |
| + } |
| + |
| bit = bmp_size << 3; |
| } |
| |
| -- |
| 2.51.0 |
| |