Blob Blame History Raw
From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
Date: Sat, 22 Oct 2022 15:35:21 +0800
Subject: [PATCH] cifs: Fix pages array leak when writedata alloc failed in
 cifs_writedata_alloc()
Git-commit: 4153d789e299b29cbc57276d687c92f3a098e59b
References: bsc#1193629
Patch-mainline: v6.1-rc3

There is a memory leak when writedata alloc failed:

  unreferenced object 0xffff888192364000 (size 8192):
    comm "sync", pid 22839, jiffies 4297313967 (age 60.230s)
    hex dump (first 32 bytes):
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    backtrace:
      [<0000000027de0814>] __kmalloc+0x4d/0x150
      [<00000000b21e81ab>] cifs_writepages+0x35f/0x14a0
      [<0000000076f7d20e>] do_writepages+0x10a/0x360
      [<00000000d6a36edc>] filemap_fdatawrite_wbc+0x95/0xc0
      [<000000005751a323>] __filemap_fdatawrite_range+0xa7/0xe0
      [<0000000088afb0ca>] file_write_and_wait_range+0x66/0xb0
      [<0000000063dbc443>] cifs_strict_fsync+0x80/0x5f0
      [<00000000c4624754>] __x64_sys_fsync+0x40/0x70
      [<000000002c0dc744>] do_syscall_64+0x35/0x80
      [<0000000052f46bee>] entry_SYSCALL_64_after_hwframe+0x46/0xb0

cifs_writepages+0x35f/0x14a0 is:
  kmalloc_array at include/linux/slab.h:628
  (inlined by) kcalloc at include/linux/slab.h:659
  (inlined by) cifs_writedata_alloc at fs/cifs/file.c:2438
  (inlined by) wdata_alloc_and_fillpages at fs/cifs/file.c:2527
  (inlined by) cifs_writepages at fs/cifs/file.c:2705

If writedata alloc failed in cifs_writedata_alloc(), the pages array
should be freed.

Fixes: 8e7360f67e75 ("CIFS: Add support for direct pages in wdata")
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: Steve French <stfrench@microsoft.com>
Acked-by: Paulo Alcantara <palcantara@suse.de>
---
 fs/cifs/file.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5b3b308e115c..d9fbf1ec6029 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2434,12 +2434,16 @@ cifs_writev_complete(struct work_struct *work)
 struct cifs_writedata *
 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
 {
+	struct cifs_writedata *writedata = NULL;
 	struct page **pages =
 		kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
-	if (pages)
-		return cifs_writedata_direct_alloc(pages, complete);
+	if (pages) {
+		writedata = cifs_writedata_direct_alloc(pages, complete);
+		if (!writedata)
+			kvfree(pages);
+	}
 
-	return NULL;
+	return writedata;
 }
 
 struct cifs_writedata *
-- 
2.38.0