aboutsummaryrefslogtreecommitdiff
path: root/fs/ceph
diff options
context:
space:
mode:
authorYan, Zheng2016-06-14 11:13:59 +0800
committerIlya Dryomov2016-07-28 02:55:39 +0200
commitfc8c3892f30c39f28fdb835f7c8598ac4cf5ed1e (patch)
treea99fe1abf02679d53681bd244fa540445f871a3e /fs/ceph
parent774a6a118c70f8c11fcfe636032b5016ad71a746 (diff)
ceph: fix use-after-free bug in ceph_direct_read_write()
ceph_aio_complete() can free the ceph_aio_request struct before the code exits the while loop. Signed-off-by: Yan, Zheng <zyan@redhat.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r--fs/ceph/file.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index ac75fa9fd858..033e88753875 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -985,6 +985,8 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
}
if (aio_req) {
+ LIST_HEAD(osd_reqs);
+
if (aio_req->num_reqs == 0) {
kfree(aio_req);
return ret;
@@ -993,8 +995,9 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
ceph_get_cap_refs(ci, write ? CEPH_CAP_FILE_WR :
CEPH_CAP_FILE_RD);
- while (!list_empty(&aio_req->osd_reqs)) {
- req = list_first_entry(&aio_req->osd_reqs,
+ list_splice(&aio_req->osd_reqs, &osd_reqs);
+ while (!list_empty(&osd_reqs)) {
+ req = list_first_entry(&osd_reqs,
struct ceph_osd_request,
r_unsafe_item);
list_del_init(&req->r_unsafe_item);