On 22.09.2016 03:15, Maxim Patlasov wrote: > struct file holds references on its f_path.mnt and f_path.dentry by calling > path_get(&f->f_path) from do_dentry_open(). Let's use the same technique > for f->f_original_path. Otherwise, f_original_path.dentry can be deleted while > file still references it leading to NULL-ptr-deref on > f->f_original_path.dentry->d_inode. > > https://jira.sw.ru/browse/PSBM-52373 > > Signed-off-by: Maxim Patlasov <mpatla...@virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktk...@virtuozzo.com> > --- > fs/file_table.c | 6 ++++++ > fs/open.c | 18 +++++++++++++++--- > 2 files changed, 21 insertions(+), 3 deletions(-) > > diff --git a/fs/file_table.c b/fs/file_table.c > index 957c476..b8982d8 100644 > --- a/fs/file_table.c > +++ b/fs/file_table.c > @@ -242,6 +242,8 @@ static void __fput(struct file *file) > struct dentry *dentry = file->f_path.dentry; > struct vfsmount *mnt = file->f_path.mnt; > struct inode *inode = dentry->d_inode; > + struct dentry *original_dentry = file->f_original_path.dentry; > + struct vfsmount *original_mnt = file->f_original_path.mnt; > > might_sleep(); > > @@ -273,10 +275,14 @@ static void __fput(struct file *file) > drop_file_write_access(file); > file->f_path.dentry = NULL; > file->f_path.mnt = NULL; > + file->f_original_path.dentry = NULL; > + file->f_original_path.mnt = NULL; > file->f_inode = NULL; > file_free(file); > dput(dentry); > mntput(mnt); > + dput(original_dentry); > + mntput(original_mnt); > } > > static DEFINE_SPINLOCK(delayed_fput_lock); > diff --git a/fs/open.c b/fs/open.c > index 8c066b1..25dbc85 100644 > --- a/fs/open.c > +++ b/fs/open.c > @@ -893,16 +893,28 @@ int vfs_open(const struct path *path, struct file *filp, > { > struct inode *inode = path->dentry->d_inode; > iop_dentry_open_t dentry_open = get_dentry_open_iop(inode); > + int do_cleanup = 0; > + int ret; > > - if (!filp->f_original_path.mnt) > + if (!filp->f_original_path.mnt) { > filp->f_original_path = *path; > + path_get(&filp->f_original_path); > + do_cleanup = 1; > + } > > if (dentry_open) > - return dentry_open(path->dentry, filp, cred); > + ret = dentry_open(path->dentry, filp, cred); > else { > filp->f_path = *path; > - return do_dentry_open(filp, NULL, cred); > + ret = do_dentry_open(filp, NULL, cred); > } > + > + if (ret && do_cleanup) { > + path_put(&filp->f_original_path); > + filp->f_original_path.mnt = NULL; > + filp->f_original_path.dentry = NULL; > + } > + return ret; > } > EXPORT_SYMBOL(vfs_open); > > _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel