Message ID | 1597942555-904-1-git-send-email-ppvk@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [V1] fuse: Fix VM_BUG_ON_PAGE issue while accessing zero ref count page | expand |
Hi Pradeep, Thank you for the patch! Yet something to improve: [auto build test ERROR on fuse/for-next] [also build test ERROR on v5.9-rc1 next-20200820] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Pradeep-P-V-K/fuse-Fix-VM_BUG_ON_PAGE-issue-while-accessing-zero-ref-count-page/20200821-005756 base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next config: x86_64-randconfig-a003-20200820 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 4deda57106f7c9b982a49cb907c33e3966c8de7f) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> fs/fuse/dev.c:955:11: error: no member named 'ff' in 'struct fuse_req' if (req->ff) ~~~ ^ fs/fuse/dev.c:956:19: error: no member named 'ff' in 'struct fuse_req' spin_lock(&req->ff->fc->lock); ~~~ ^ fs/fuse/dev.c:968:11: error: no member named 'ff' in 'struct fuse_req' if (req->ff) ~~~ ^ fs/fuse/dev.c:969:21: error: no member named 'ff' in 'struct fuse_req' spin_unlock(&req->ff->fc->lock); ~~~ ^ 4 errors generated. # https://github.com/0day-ci/linux/commit/776d24e60b6fdfbd88fc0cf0bf04859293d42bd6 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Pradeep-P-V-K/fuse-Fix-VM_BUG_ON_PAGE-issue-while-accessing-zero-ref-count-page/20200821-005756 git checkout 776d24e60b6fdfbd88fc0cf0bf04859293d42bd6 vim +955 fs/fuse/dev.c 945 946 /* Copy pages in the request to/from userspace buffer */ 947 static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 948 int zeroing) 949 { 950 unsigned i; 951 int err = 0; 952 struct fuse_req *req = cs->req; 953 struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args); 954 > 955 if (req->ff) 956 spin_lock(&req->ff->fc->lock); 957 for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { 958 unsigned int offset = ap->descs[i].offset; 959 unsigned int count = min(nbytes, ap->descs[i].length); 960 961 err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); 962 if (err) 963 goto err; 964 965 nbytes -= count; 966 } 967 err: 968 if (req->ff) 969 spin_unlock(&req->ff->fc->lock); 970 return err; 971 } 972 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 02b3c36..ca4f63c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -948,22 +948,26 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, int zeroing) { unsigned i; + int err = 0; struct fuse_req *req = cs->req; struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args); - + if (req->ff) + spin_lock(&req->ff->fc->lock); for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { - int err; unsigned int offset = ap->descs[i].offset; unsigned int count = min(nbytes, ap->descs[i].length); err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); if (err) - return err; + goto err; nbytes -= count; } - return 0; +err: + if (req->ff) + spin_unlock(&req->ff->fc->lock); + return err; } /* Copy a single argument in the request to/from userspace buffer */
There is a potential race between fuse_abort_conn() and fuse_copy_page() as shown below, due to which VM_BUG_ON_PAGE crash is observed. context#1: context#2: fuse_dev_do_read() fuse_abort_conn() ->fuse_copy_args() ->end_requests() ->fuse_copy_pages() ->request_end() ->fuse_copy_page() ->fuse_writepage_end) ->fuse_ref_page() ->fuse_writepage_free() ->__free_page() ->put_page_testzero() ->get_page() ->VM_BUG_ON_PAGE() This results in below crash as when ->put_page_testzero() in context#2 decrease the page reference and get_page() in context#1 accessed it with zero page reference count. [ 174.391095] (1)[10406:Thread-6]page dumped because: VM_BUG_ON_PAGE(((unsigned int) page_ref_count(page) + 127u <= 127u)) [ 174.391113] (1)[10406:Thread-6]page allocated via order 0, migratetype Unmovable, gfp_mask 0x620042(GFP_NOFS|__GFP_HIGHMEM|__GFP_HARDWALL), pid 261, ts 174390946312 ns [ 174.391135] (1)[10406:Thread-6] prep_new_page+0x13c/0x210 [ 174.391148] (1)[10406:Thread-6] get_page_from_freelist+0x21ac/0x2370 [ 174.391161] (1)[10406:Thread-6] __alloc_pages_nodemask+0x244/0x14a8 [ 174.391176] (1)[10406:Thread-6] fuse_writepages_fill+0x150/0x708 [ 174.391190] (1)[10406:Thread-6] write_cache_pages+0x3d8/0x550 [ 174.391202] (1)[10406:Thread-6] fuse_writepages+0x94/0x130 [ 174.391214] (1)[10406:Thread-6] do_writepages+0x74/0x140 [ 174.391228] (1)[10406:Thread-6] __writeback_single_inode+0x168/0x788 [ 174.391239] (1)[10406:Thread-6] writeback_sb_inodes+0x56c/0xab8 [ 174.391251] (1)[10406:Thread-6] __writeback_inodes_wb+0x94/0x180 [ 174.391262] (1)[10406:Thread-6] wb_writeback+0x318/0x618 [ 174.391274] (1)[10406:Thread-6] wb_workfn+0x468/0x828 [ 174.391290] (1)[10406:Thread-6] process_one_work+0x3d0/0x720 [ 174.391302] (1)[10406:Thread-6] worker_thread+0x234/0x4c0 [ 174.391314] (1)[10406:Thread-6] kthread+0x144/0x158 [ 174.391327] (1)[10406:Thread-6] ret_from_fork+0x10/0x1c [ 174.391363] (1)[10406:Thread-6]------------[ cut here ]------------ [ 174.391371] (1)[10406:Thread-6]kernel BUG at include/linux/mm.h:980! [ 174.391381] (1)[10406:Thread-6]Internal error: Oops - BUG: 0 [#1] ... [ 174.486928] (1)[10406:Thread-6]pc : fuse_copy_page+0x750/0x790 [ 174.493029] (1)[10406:Thread-6]lr : fuse_copy_page+0x750/0x790 [ 174.718831] (1)[10406:Thread-6] fuse_copy_page+0x750/0x790 [ 174.718838] (1)[10406:Thread-6] fuse_copy_args+0xb4/0x1e8 [ 174.718843] (1)[10406:Thread-6] fuse_dev_do_read+0x424/0x888 [ 174.718848] (1)[10406:Thread-6] fuse_dev_splice_read+0x94/0x200 [ 174.718856] (1)[10406:Thread-6] __arm64_sys_splice+0x874/0xb20 [ 174.718864] (1)[10406:Thread-6] el0_svc_common+0xc8/0x240 [ 174.718869] (1)[10406:Thread-6] el0_svc_handler+0x6c/0x88 [ 174.718875] (1)[10406:Thread-6] el0_svc+0x8/0xc [ 174.778853] (1)[10406:Thread-6]Kernel panic - not syncing: Fatal Fix this by protecting fuse_copy_pages() with fc->lock. Signed-off-by: Pradeep P V K <ppvk@codeaurora.org> --- fs/fuse/dev.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)