diff options
author | Konstantin Komarov <almaz.alexandrovich@paragon-software.com> | 2024-06-03 13:13:17 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-07-27 11:36:15 +0200 |
commit | c114d2b88f8b226d4b2acf5a1ba0412cde6c31dd (patch) | |
tree | 6b11f581071001d9c2493fd474a1e106f3de4051 | |
parent | f4435f476b9bf059cd9e26a69f5b29c768d00375 (diff) | |
download | linux-stable-c114d2b88f8b226d4b2acf5a1ba0412cde6c31dd.tar.gz linux-stable-c114d2b88f8b226d4b2acf5a1ba0412cde6c31dd.tar.bz2 linux-stable-c114d2b88f8b226d4b2acf5a1ba0412cde6c31dd.zip |
fs/ntfs3: Add a check for attr_names and oatbl
commit 702d4930eb06dcfda85a2fa67e8a1a27bfa2a845 upstream.
Added out-of-bound checking for *ane (ATTR_NAME_ENTRY).
Reported-by: lei lu <llfamsec@gmail.com>
Fixes: 865e7a7700d93 ("fs/ntfs3: Reduce stack usage")
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | fs/ntfs3/fslog.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 4085fe30bf48..2e2348f8e285 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -3722,6 +3722,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) u64 rec_lsn, checkpt_lsn = 0, rlsn = 0; struct ATTR_NAME_ENTRY *attr_names = NULL; + u32 attr_names_bytes = 0; + u32 oatbl_bytes = 0; struct RESTART_TABLE *dptbl = NULL; struct RESTART_TABLE *trtbl = NULL; const struct RESTART_TABLE *rt; @@ -3736,6 +3738,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized) struct NTFS_RESTART *rst = NULL; struct lcb *lcb = NULL; struct OPEN_ATTR_ENRTY *oe; + struct ATTR_NAME_ENTRY *ane; struct TRANSACTION_ENTRY *tr; struct DIR_PAGE_ENTRY *dp; u32 i, bytes_per_attr_entry; @@ -4314,17 +4317,40 @@ check_attr_table: lcb = NULL; check_attribute_names2: - if (rst->attr_names_len && oatbl) { - struct ATTR_NAME_ENTRY *ane = attr_names; - while (ane->off) { + if (attr_names && oatbl) { + off = 0; + for (;;) { + /* Check we can use attribute name entry 'ane'. */ + static_assert(sizeof(*ane) == 4); + if (off + sizeof(*ane) > attr_names_bytes) { + /* just ignore the rest. */ + break; + } + + ane = Add2Ptr(attr_names, off); + t16 = le16_to_cpu(ane->off); + if (!t16) { + /* this is the only valid exit. */ + break; + } + + /* Check we can use open attribute entry 'oe'. */ + if (t16 + sizeof(*oe) > oatbl_bytes) { + /* just ignore the rest. */ + break; + } + /* TODO: Clear table on exit! */ - oe = Add2Ptr(oatbl, le16_to_cpu(ane->off)); + oe = Add2Ptr(oatbl, t16); t16 = le16_to_cpu(ane->name_bytes); + off += t16 + sizeof(*ane); + if (off > attr_names_bytes) { + /* just ignore the rest. */ + break; + } oe->name_len = t16 / sizeof(short); oe->ptr = ane->name; oe->is_attr_name = 2; - ane = Add2Ptr(ane, - sizeof(struct ATTR_NAME_ENTRY) + t16); } } |