Skip to content

Commit 9c1c2b3

Browse files
jtlaytonidryomov
authored andcommitted
ceph: hold extra reference to r_parent over life of request
Currently, we just assume that it will stick around by virtue of the submitter's reference, but later patches will allow the syscall to return early and we can't rely on that reference at that point. While I'm not aware of any reports of it, Xiubo pointed out that this may fix a use-after-free. If the wait for a reply times out or is canceled via signal, and then the reply comes in after the syscall returns, the client can end up trying to access r_parent without a reference. Take an extra reference to the inode when setting r_parent and release it when releasing the request. Cc: stable@vger.kernel.org Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
1 parent def9d27 commit 9c1c2b3

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

fs/ceph/mds_client.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,8 +708,10 @@ void ceph_mdsc_release_request(struct kref *kref)
708708
/* avoid calling iput_final() in mds dispatch threads */
709709
ceph_async_iput(req->r_inode);
710710
}
711-
if (req->r_parent)
711+
if (req->r_parent) {
712712
ceph_put_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN);
713+
ceph_async_iput(req->r_parent);
714+
}
713715
ceph_async_iput(req->r_target_inode);
714716
if (req->r_dentry)
715717
dput(req->r_dentry);
@@ -2676,8 +2678,10 @@ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
26762678
/* take CAP_PIN refs for r_inode, r_parent, r_old_dentry */
26772679
if (req->r_inode)
26782680
ceph_get_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN);
2679-
if (req->r_parent)
2681+
if (req->r_parent) {
26802682
ceph_get_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN);
2683+
ihold(req->r_parent);
2684+
}
26812685
if (req->r_old_dentry_dir)
26822686
ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
26832687
CEPH_CAP_PIN);

0 commit comments

Comments
 (0)