Unverified Commit ecfbd57c authored by Yin Xiujiang's avatar Yin Xiujiang Committed by Konstantin Komarov
Browse files

fs/ntfs3: Fix slab-out-of-bounds in r_page



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: default avatarYin Xiujiang <yinxiujiang@kylinos.cn>
Signed-off-by: default avatarKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
parent 65801516
Loading
Loading
Loading
Loading
+2 −24
Original line number Diff line number Diff line
@@ -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));