mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 14:11:20 +00:00
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 <syzbot+32c236387d66c4516827@syzkaller.appspotmail.com>
Fixes: bafa96541b
("[PATCH] fuse: add control filesystem")
Cc: <stable@vger.kernel.org> # v2.6.18
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
8a301eb16d
commit
6becdb601b
1 changed files with 10 additions and 3 deletions
|
@ -211,10 +211,11 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fc->ctl_dentry[fc->ctl_ndents++] = dentry;
|
|
||||||
inode = new_inode(fuse_control_sb);
|
inode = new_inode(fuse_control_sb);
|
||||||
if (!inode)
|
if (!inode) {
|
||||||
|
dput(dentry);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
inode->i_ino = get_next_ino();
|
inode->i_ino = get_next_ino();
|
||||||
inode->i_mode = mode;
|
inode->i_mode = mode;
|
||||||
|
@ -228,6 +229,9 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
|
||||||
set_nlink(inode, nlink);
|
set_nlink(inode, nlink);
|
||||||
inode->i_private = fc;
|
inode->i_private = fc;
|
||||||
d_add(dentry, inode);
|
d_add(dentry, inode);
|
||||||
|
|
||||||
|
fc->ctl_dentry[fc->ctl_ndents++] = dentry;
|
||||||
|
|
||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +288,10 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
|
||||||
for (i = fc->ctl_ndents - 1; i >= 0; i--) {
|
for (i = fc->ctl_ndents - 1; i >= 0; i--) {
|
||||||
struct dentry *dentry = fc->ctl_dentry[i];
|
struct dentry *dentry = fc->ctl_dentry[i];
|
||||||
d_inode(dentry)->i_private = NULL;
|
d_inode(dentry)->i_private = NULL;
|
||||||
d_drop(dentry);
|
if (!i) {
|
||||||
|
/* Get rid of submounts: */
|
||||||
|
d_invalidate(dentry);
|
||||||
|
}
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
}
|
}
|
||||||
drop_nlink(d_inode(fuse_control_sb->s_root));
|
drop_nlink(d_inode(fuse_control_sb->s_root));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue