f2fs: fix NULL pointer dereference in f2fs_write_begin()
authorChao Yu <yuchao0@huawei.com>
Thu, 19 Mar 2020 11:58:00 +0000 (19:58 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Apr 2020 08:36:39 +0000 (10:36 +0200)
[ Upstream commit 62f63eea291b50a5677ae7503ac128803174698a ]

BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: 0010:f2fs_write_begin+0x823/0xb90 [f2fs]
Call Trace:
 f2fs_quota_write+0x139/0x1d0 [f2fs]
 write_blk+0x36/0x80 [quota_tree]
 get_free_dqblk+0x42/0xa0 [quota_tree]
 do_insert_tree+0x235/0x4a0 [quota_tree]
 do_insert_tree+0x26e/0x4a0 [quota_tree]
 do_insert_tree+0x26e/0x4a0 [quota_tree]
 do_insert_tree+0x26e/0x4a0 [quota_tree]
 qtree_write_dquot+0x70/0x190 [quota_tree]
 v2_write_dquot+0x43/0x90 [quota_v2]
 dquot_acquire+0x77/0x100
 f2fs_dquot_acquire+0x2f/0x60 [f2fs]
 dqget+0x310/0x450
 dquot_transfer+0x7e/0x120
 f2fs_setattr+0x11a/0x4a0 [f2fs]
 notify_change+0x349/0x480
 chown_common+0x168/0x1c0
 do_fchownat+0xbc/0xf0
 __x64_sys_fchownat+0x20/0x30
 do_syscall_64+0x5f/0x220
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

Passing fsdata parameter to .write_{begin,end} in f2fs_quota_write(),
so that if quota file is compressed one, we can avoid above NULL
pointer dereference when updating quota content.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/f2fs/super.c

index 94caf26..5e1d4d9 100644 (file)
@@ -1826,6 +1826,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
        int offset = off & (sb->s_blocksize - 1);
        size_t towrite = len;
        struct page *page;
+       void *fsdata = NULL;
        char *kaddr;
        int err = 0;
        int tocopy;
@@ -1835,7 +1836,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
                                                                towrite);
 retry:
                err = a_ops->write_begin(NULL, mapping, off, tocopy, 0,
-                                                       &page, NULL);
+                                                       &page, &fsdata);
                if (unlikely(err)) {
                        if (err == -ENOMEM) {
                                congestion_wait(BLK_RW_ASYNC, HZ/50);
@@ -1851,7 +1852,7 @@ retry:
                flush_dcache_page(page);
 
                a_ops->write_end(NULL, mapping, off, tocopy, tocopy,
-                                               page, NULL);
+                                               page, fsdata);
                offset = 0;
                towrite -= tocopy;
                off += tocopy;