mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
fs/ntfs3: bound page_lcns[] index by the log record
The copy_lcns loop and the redo shorten loop index page_lcns[] at j + i,
where i runs up to the log record's lcns_follow. That count is checked only
against the record's own length, not the target entry, so check_dp_table()
(which validates the entry's lcns_follow) does not cover it: the copy_lcns
entry may even be freshly allocated after that check, and find_dp() bounds j
but not i. A crafted record thus overflows page_lcns[] of an otherwise valid
entry.
Add dp_range_ok() and reject, before each loop, any record whose run does
not fit the entry. These are the only two page_lcns[] accesses indexed by
the record rather than the entry, so together with the entry validation
every access is now bounded.
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>
[almaz.alexandrovich@paragon-software.com: original patch contained changes to the problem already handled, applied partly]
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
This commit is contained in:
parent
006cb7713d
commit
6f7b9dbdc1
|
|
@ -647,6 +647,14 @@ static inline void *enum_rstbl(struct RESTART_TABLE *t, void *c)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_range_ok - true if [j, j + count) fits in a page_lcns[cap] array.
|
||||
*/
|
||||
static inline bool dp_range_ok(size_t j, u32 count, u32 cap)
|
||||
{
|
||||
return j < cap && count <= cap - j;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_dp - Search for a @vcn in Dirty Page Table.
|
||||
*/
|
||||
|
|
@ -5104,6 +5112,13 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
|
|||
/* Shorten length by any Lcns which were deleted. */
|
||||
saved_len = dlen;
|
||||
|
||||
if (!dp_range_ok(le64_to_cpu(lrh->target_vcn) - le64_to_cpu(dp->vcn),
|
||||
le16_to_cpu(lrh->lcns_follow),
|
||||
le32_to_cpu(dp->lcns_follow))) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = le16_to_cpu(lrh->lcns_follow); i; i--) {
|
||||
size_t j;
|
||||
u32 alen, voff;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user