fs/ntfs3: Fix slab-out-of-bounds in r_page
authorYin Xiujiang <yinxiujiang@kylinos.cn>
Mon, 6 Dec 2021 02:40:45 +0000 (10:40 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Jan 2023 10:58:45 +0000 (11:58 +0100)
[ Upstream commit ecfbd57cf9c5ca225184ae266ce44ae473792132 ]

When PAGE_SIZE is 64K, if read_log_page is called by log_read_rst for
the first time, the size of *buffer would be equal to
DefaultLogPageSize(4K).But for *buffer operations like memcpy,
if the memory area size(n) which being assigned to buffer is larger
than 4K (log->page_size(64K) or bytes(64K-page_off)), it will cause
an out of boundary error.
 Call trace:
  [...]
  kasan_report+0x44/0x130
  check_memory_region+0xf8/0x1a0
  memcpy+0xc8/0x100
  ntfs_read_run_nb+0x20c/0x460
  read_log_page+0xd0/0x1f4
  log_read_rst+0x110/0x75c
  log_replay+0x1e8/0x4aa0
  ntfs_loadlog_and_replay+0x290/0x2d0
  ntfs_fill_super+0x508/0xec0
  get_tree_bdev+0x1fc/0x34c
  [...]

Fix this by setting variable r_page to NULL in log_read_rst.

Signed-off-by: Yin Xiujiang <yinxiujiang@kylinos.cn>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/ntfs3/fslog.c

index bcdddcd..20abdb2 100644 (file)
@@ -1132,7 +1132,7 @@ static int read_log_page(struct ntfs_log *log, u32 vbo,
                return -EINVAL;
 
        if (!*buffer) {
-               to_free = kmalloc(bytes, GFP_NOFS);
+               to_free = kmalloc(log->page_size, GFP_NOFS);
                if (!to_free)
                        return -ENOMEM;
                *buffer = to_free;
@@ -1180,10 +1180,7 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
                        struct restart_info *info)
 {
        u32 skip, vbo;
-       struct RESTART_HDR *r_page = kmalloc(DefaultLogPageSize, GFP_NOFS);
-
-       if (!r_page)
-               return -ENOMEM;
+       struct RESTART_HDR *r_page = NULL;
 
        /* Determine which restart area we are looking for. */
        if (first) {
@@ -1197,7 +1194,6 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
        /* Loop continuously until we succeed. */
        for (; vbo < l_size; vbo = 2 * vbo + skip, skip = 0) {
                bool usa_error;
-               u32 sys_page_size;
                bool brst, bchk;
                struct RESTART_AREA *ra;
 
@@ -1251,24 +1247,6 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
                        goto check_result;
                }
 
-               /* Read the entire restart area. */
-               sys_page_size = le32_to_cpu(r_page->sys_page_size);
-               if (DefaultLogPageSize != sys_page_size) {
-                       kfree(r_page);
-                       r_page = kzalloc(sys_page_size, GFP_NOFS);
-                       if (!r_page)
-                               return -ENOMEM;
-
-                       if (read_log_page(log, vbo,
-                                         (struct RECORD_PAGE_HDR **)&r_page,
-                                         &usa_error)) {
-                               /* Ignore any errors. */
-                               kfree(r_page);
-                               r_page = NULL;
-                               continue;
-                       }
-               }
-
                if (is_client_area_valid(r_page, usa_error)) {
                        info->valid_page = true;
                        ra = Add2Ptr(r_page, le16_to_cpu(r_page->ra_off));