The commit is pushed to "branch-rh7-3.10.0-327.28.2.vz7.17.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-327.28.2.vz7.17.9 ------> commit 0c898c51709daf78d1704b90bec1395cadeb3a51 Author: Maxim Patlasov <mpatla...@virtuozzo.com> Date: Fri Sep 23 17:32:01 2016 +0400
fs: hold reference on original path 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