Skip to content

Commit 6becdb6

Browse files
author
Miklos Szeredi
committed
fuse: fix control dir setup and teardown
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 <[email protected]> Fixes: bafa965 ("[PATCH] fuse: add control filesystem") Cc: <[email protected]> # v2.6.18 Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 8a301eb commit 6becdb6

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

fs/fuse/control.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,11 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
211211
if (!dentry)
212212
return NULL;
213213

214-
fc->ctl_dentry[fc->ctl_ndents++] = dentry;
215214
inode = new_inode(fuse_control_sb);
216-
if (!inode)
215+
if (!inode) {
216+
dput(dentry);
217217
return NULL;
218+
}
218219

219220
inode->i_ino = get_next_ino();
220221
inode->i_mode = mode;
@@ -228,6 +229,9 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
228229
set_nlink(inode, nlink);
229230
inode->i_private = fc;
230231
d_add(dentry, inode);
232+
233+
fc->ctl_dentry[fc->ctl_ndents++] = dentry;
234+
231235
return dentry;
232236
}
233237

@@ -284,7 +288,10 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
284288
for (i = fc->ctl_ndents - 1; i >= 0; i--) {
285289
struct dentry *dentry = fc->ctl_dentry[i];
286290
d_inode(dentry)->i_private = NULL;
287-
d_drop(dentry);
291+
if (!i) {
292+
/* Get rid of submounts: */
293+
d_invalidate(dentry);
294+
}
288295
dput(dentry);
289296
}
290297
drop_nlink(d_inode(fuse_control_sb->s_root));

0 commit comments

Comments
 (0)