diff options
author | 2019-04-29 11:51:02 -0400 | |
---|---|---|
committer | 2019-05-07 19:22:37 +0200 | |
commit | 964fff7491e4923e18ff08f2a254c4b94e3f83d6 (patch) | |
tree | d9a103227b8586c155dd44ac8b566c151d8b6f19 /fs/ceph | |
parent | ceph: fix potential use-after-free in ceph_mdsc_build_path (diff) | |
download | linux-964fff7491e4923e18ff08f2a254c4b94e3f83d6.tar.gz linux-964fff7491e4923e18ff08f2a254c4b94e3f83d6.tar.bz2 linux-964fff7491e4923e18ff08f2a254c4b94e3f83d6.zip |
ceph: use ceph_mdsc_build_path instead of clone_dentry_name
While it may be slightly more efficient, it's probably not worthwhile to
optimize for the case that clone_dentry_name handles. We can get the
same result by just calling ceph_mdsc_build_path when the parent isn't
locked, with less code duplication.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/mds_client.c | 42 |
1 files changed, 3 insertions, 39 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index b01e2043b1b2..7af722834348 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2172,56 +2172,20 @@ retry: return path; } -/* Duplicate the dentry->d_name.name safely */ -static int clone_dentry_name(struct dentry *dentry, const char **ppath, - int *ppathlen) -{ - u32 len; - char *name; - -retry: - len = READ_ONCE(dentry->d_name.len); - name = kmalloc(len + 1, GFP_NOFS); - if (!name) - return -ENOMEM; - - spin_lock(&dentry->d_lock); - if (dentry->d_name.len != len) { - spin_unlock(&dentry->d_lock); - kfree(name); - goto retry; - } - memcpy(name, dentry->d_name.name, len); - spin_unlock(&dentry->d_lock); - - name[len] = '\0'; - *ppath = name; - *ppathlen = len; - return 0; -} - static int build_dentry_path(struct dentry *dentry, struct inode *dir, const char **ppath, int *ppathlen, u64 *pino, bool *pfreepath, bool parent_locked) { - int ret; char *path; rcu_read_lock(); if (!dir) dir = d_inode_rcu(dentry->d_parent); - if (dir && ceph_snap(dir) == CEPH_NOSNAP) { + if (dir && parent_locked && ceph_snap(dir) == CEPH_NOSNAP) { *pino = ceph_ino(dir); rcu_read_unlock(); - if (parent_locked) { - *ppath = dentry->d_name.name; - *ppathlen = dentry->d_name.len; - } else { - ret = clone_dentry_name(dentry, ppath, ppathlen); - if (ret) - return ret; - *pfreepath = true; - } + *ppath = dentry->d_name.name; + *ppathlen = dentry->d_name.len; return 0; } rcu_read_unlock(); |