mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
fs/ntfs3: validate dirty page table on log replay
Each DIR_PAGE_ENTRY ends in a page_lcns[] array whose length is the on-disk
lcns_follow field. check_rstbl() validates the table bookkeeping but never
checks that this array fits in the entry, so a crafted lcns_follow lets the
v0->v1 conversion memmove and later replay passes run off the entry.
Add check_dp_table() to reject, right after check_rstbl(), any entry larger
than its size claims via struct_size() (the same expression used to allocate
these entries, so the check is overflow-safe by construction). All consumers
can then trust lcns_follow as the real capacity. This covers every
page_lcns[] access whose index is bounded by the entry itself (the
conversion memmove, the HotFix store via find_dp(), and the self-bounded
scan loops). Accesses whose index comes from the log record need a separate
bound and are handled in a follow-up patch.
Fixes: b46acd6a6a ("fs/ntfs3: Add NTFS journal")
Cc: stable@vger.kernel.org
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
This commit is contained in:
parent
111f8d74a1
commit
006cb7713d
|
|
@ -789,6 +789,20 @@ static bool check_rstbl(const struct RESTART_TABLE *rt, size_t bytes)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool check_dp_table(const struct RESTART_TABLE *dptbl)
|
||||
{
|
||||
u32 rsize = le16_to_cpu(dptbl->size);
|
||||
struct DIR_PAGE_ENTRY *dp = NULL;
|
||||
|
||||
while ((dp = enum_rstbl((struct RESTART_TABLE *)dptbl, dp))) {
|
||||
if (struct_size(dp, page_lcns, le32_to_cpu(dp->lcns_follow)) >
|
||||
rsize)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* free_rsttbl_idx - Free a previously allocated index a Restart Table.
|
||||
*/
|
||||
|
|
@ -4293,6 +4307,11 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!check_dp_table(rt)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dptbl = kmemdup(rt, t32, GFP_NOFS);
|
||||
if (!dptbl) {
|
||||
err = -ENOMEM;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user