summary refs log tree commit diff
path: root/fs/ceph
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-06-14 11:13:59 +0800
committerIlya Dryomov <idryomov@gmail.com>2016-07-28 02:55:39 +0200
commitfc8c3892f30c39f28fdb835f7c8598ac4cf5ed1e (patch)
treea99fe1abf02679d53681bd244fa540445f871a3e /fs/ceph
parent774a6a118c70f8c11fcfe636032b5016ad71a746 (diff)
downloadlinux-fc8c3892f30c39f28fdb835f7c8598ac4cf5ed1e.tar.gz
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);