diff mbox series

[1/2] cifs: Fix pages leak when writedata alloc failed in cifs_write_from_iter()

Message ID 20221022073521.1660841-2-zhangxiaoxu5@huawei.com (mailing list archive)
State New, archived
Headers show
Series Fix memory and page leak when writedata alloc failed | expand

Commit Message

Zhang Xiaoxu Oct. 22, 2022, 7:35 a.m. UTC
There is a kmemleak when writedata alloc failed:

  unreferenced object 0xffff888175ae4000 (size 4096):
    comm "dd", pid 19419, jiffies 4296028749 (age 739.396s)
    hex dump (first 32 bytes):
      80 02 b0 04 00 ea ff ff c0 02 b0 04 00 ea ff ff  ................
      80 22 4c 04 00 ea ff ff c0 22 4c 04 00 ea ff ff  ."L......"L.....
    backtrace:
      [<0000000072fdbb86>] __kmalloc_node+0x50/0x150
      [<0000000039faf56f>] __iov_iter_get_pages_alloc+0x605/0xdd0
      [<00000000f862a9d4>] iov_iter_get_pages_alloc2+0x3b/0x80
      [<000000008f226067>] cifs_write_from_iter+0x2ae/0xe40
      [<000000001f78f2f1>] __cifs_writev+0x337/0x5c0
      [<00000000257fcef5>] vfs_write+0x503/0x690
      [<000000008778a238>] ksys_write+0xb9/0x150
      [<00000000ed82047c>] do_syscall_64+0x35/0x80
      [<000000003365551d>] entry_SYSCALL_64_after_hwframe+0x46/0xb0

__iov_iter_get_pages_alloc+0x605/0xdd0 is:
  want_pages_array at lib/iov_iter.c:1304
  (inlined by) __iov_iter_get_pages_alloc at lib/iov_iter.c:1457

If writedata allocate failed, the pages and pagevec should be cleanup.

Fixes: 8c5f9c1ab7cb ("CIFS: Add support for direct I/O write")
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
---
 fs/cifs/file.c | 3 +++
 1 file changed, 3 insertions(+)
diff mbox series

Patch

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5b3b308e115c..87be0223a57a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3299,6 +3299,9 @@  cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
 					     cifs_uncached_writev_complete);
 			if (!wdata) {
 				rc = -ENOMEM;
+				for (i = 0; i < nr_pages; i++)
+					put_page(pagevec[i]);
+				kvfree(pagevec);
 				add_credits_and_wake_if(server, credits, 0);
 				break;
 			}