| From e8f3bd773d22f488724dffb886a1618da85c2966 Mon Sep 17 00:00:00 2001 |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| Date: Thu, 26 Jul 2018 16:13:11 +0200 |
| Subject: fuse: Fix oops at process_init_reply() |
| |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| |
| commit e8f3bd773d22f488724dffb886a1618da85c2966 upstream. |
| |
| syzbot is hitting NULL pointer dereference at process_init_reply(). |
| This is because deactivate_locked_super() is called before response for |
| initial request is processed. |
| |
| Fix this by aborting and waiting for all requests (including FUSE_INIT) |
| before resetting fc->sb. |
| |
| Original patch by Tetsuo Handa <penguin-kernel@I-love.SKAURA.ne.jp>. |
| |
| Reported-by: syzbot <syzbot+b62f08f4d5857755e3bc@syzkaller.appspotmail.com> |
| Fixes: e27c9d3877a0 ("fuse: fuse: add time_gran to INIT_OUT") |
| Cc: <stable@vger.kernel.org> # v3.19 |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/fuse/inode.c | 25 +++++++++++-------------- |
| 1 file changed, 11 insertions(+), 14 deletions(-) |
| |
| --- a/fs/fuse/inode.c |
| +++ b/fs/fuse/inode.c |
| @@ -397,11 +397,6 @@ static void fuse_put_super(struct super_ |
| { |
| struct fuse_conn *fc = get_fuse_conn_super(sb); |
| |
| - fuse_send_destroy(fc); |
| - |
| - fuse_abort_conn(fc); |
| - fuse_wait_aborted(fc); |
| - |
| mutex_lock(&fuse_mutex); |
| list_del(&fc->entry); |
| fuse_ctl_remove_conn(fc); |
| @@ -1198,16 +1193,25 @@ static struct dentry *fuse_mount(struct |
| return mount_nodev(fs_type, flags, raw_data, fuse_fill_super); |
| } |
| |
| -static void fuse_kill_sb_anon(struct super_block *sb) |
| +static void fuse_sb_destroy(struct super_block *sb) |
| { |
| struct fuse_conn *fc = get_fuse_conn_super(sb); |
| |
| if (fc) { |
| + fuse_send_destroy(fc); |
| + |
| + fuse_abort_conn(fc); |
| + fuse_wait_aborted(fc); |
| + |
| down_write(&fc->killsb); |
| fc->sb = NULL; |
| up_write(&fc->killsb); |
| } |
| +} |
| |
| +static void fuse_kill_sb_anon(struct super_block *sb) |
| +{ |
| + fuse_sb_destroy(sb); |
| kill_anon_super(sb); |
| } |
| |
| @@ -1230,14 +1234,7 @@ static struct dentry *fuse_mount_blk(str |
| |
| static void fuse_kill_sb_blk(struct super_block *sb) |
| { |
| - struct fuse_conn *fc = get_fuse_conn_super(sb); |
| - |
| - if (fc) { |
| - down_write(&fc->killsb); |
| - fc->sb = NULL; |
| - up_write(&fc->killsb); |
| - } |
| - |
| + fuse_sb_destroy(sb); |
| kill_block_super(sb); |
| } |
| |