[PATCH 4.9 023/101] fuse: fix control dir setup and teardown

2018-07-01 Thread Greg Kroah-Hartman
4.9-stable review patch.  If anyone has any objections, please let me know.

--

From: Miklos Szeredi 

commit 6becdb601bae2a043d7fb9762c4d48699528ea6e upstream.

syzbot is reporting NULL pointer dereference at fuse_ctl_remove_conn() [1].
Since fc->ctl_ndents is incremented by fuse_ctl_add_conn() when new_inode()
failed, fuse_ctl_remove_conn() reaches an inode-less dentry and tries to
clear d_inode(dentry)->i_private field.

Fix by only adding the dentry to the array after being fully set up.

When tearing down the control directory, do d_invalidate() on it to get rid
of any mounts that might have been added.

[1] 
https://syzkaller.appspot.com/bug?id=f396d863067238959c91c0b7cfc10b163638cac6
Reported-by: syzbot 
Fixes: bafa96541b25 ("[PATCH] fuse: add control filesystem")
Cc:  # v2.6.18
Signed-off-by: Miklos Szeredi 
Signed-off-by: Greg Kroah-Hartman 

---
 fs/fuse/control.c |   13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -211,10 +211,11 @@ static struct dentry *fuse_ctl_add_dentr
if (!dentry)
return NULL;
 
-   fc->ctl_dentry[fc->ctl_ndents++] = dentry;
inode = new_inode(fuse_control_sb);
-   if (!inode)
+   if (!inode) {
+   dput(dentry);
return NULL;
+   }
 
inode->i_ino = get_next_ino();
inode->i_mode = mode;
@@ -228,6 +229,9 @@ static struct dentry *fuse_ctl_add_dentr
set_nlink(inode, nlink);
inode->i_private = fc;
d_add(dentry, inode);
+
+   fc->ctl_dentry[fc->ctl_ndents++] = dentry;
+
return dentry;
 }
 
@@ -284,7 +288,10 @@ void fuse_ctl_remove_conn(struct fuse_co
for (i = fc->ctl_ndents - 1; i >= 0; i--) {
struct dentry *dentry = fc->ctl_dentry[i];
d_inode(dentry)->i_private = NULL;
-   d_drop(dentry);
+   if (!i) {
+   /* Get rid of submounts: */
+   d_invalidate(dentry);
+   }
dput(dentry);
}
drop_nlink(d_inode(fuse_control_sb->s_root));




[PATCH 4.9 023/101] fuse: fix control dir setup and teardown

2018-07-01 Thread Greg Kroah-Hartman
4.9-stable review patch.  If anyone has any objections, please let me know.

--

From: Miklos Szeredi 

commit 6becdb601bae2a043d7fb9762c4d48699528ea6e upstream.

syzbot is reporting NULL pointer dereference at fuse_ctl_remove_conn() [1].
Since fc->ctl_ndents is incremented by fuse_ctl_add_conn() when new_inode()
failed, fuse_ctl_remove_conn() reaches an inode-less dentry and tries to
clear d_inode(dentry)->i_private field.

Fix by only adding the dentry to the array after being fully set up.

When tearing down the control directory, do d_invalidate() on it to get rid
of any mounts that might have been added.

[1] 
https://syzkaller.appspot.com/bug?id=f396d863067238959c91c0b7cfc10b163638cac6
Reported-by: syzbot 
Fixes: bafa96541b25 ("[PATCH] fuse: add control filesystem")
Cc:  # v2.6.18
Signed-off-by: Miklos Szeredi 
Signed-off-by: Greg Kroah-Hartman 

---
 fs/fuse/control.c |   13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -211,10 +211,11 @@ static struct dentry *fuse_ctl_add_dentr
if (!dentry)
return NULL;
 
-   fc->ctl_dentry[fc->ctl_ndents++] = dentry;
inode = new_inode(fuse_control_sb);
-   if (!inode)
+   if (!inode) {
+   dput(dentry);
return NULL;
+   }
 
inode->i_ino = get_next_ino();
inode->i_mode = mode;
@@ -228,6 +229,9 @@ static struct dentry *fuse_ctl_add_dentr
set_nlink(inode, nlink);
inode->i_private = fc;
d_add(dentry, inode);
+
+   fc->ctl_dentry[fc->ctl_ndents++] = dentry;
+
return dentry;
 }
 
@@ -284,7 +288,10 @@ void fuse_ctl_remove_conn(struct fuse_co
for (i = fc->ctl_ndents - 1; i >= 0; i--) {
struct dentry *dentry = fc->ctl_dentry[i];
d_inode(dentry)->i_private = NULL;
-   d_drop(dentry);
+   if (!i) {
+   /* Get rid of submounts: */
+   d_invalidate(dentry);
+   }
dput(dentry);
}
drop_nlink(d_inode(fuse_control_sb->s_root));