ceph: fix use-after-free bug in ceph_direct_read_write()
authorYan, Zheng <zyan@redhat.com>
Tue, 14 Jun 2016 03:13:59 +0000 (11:13 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 28 Jul 2016 00:55:39 +0000 (02:55 +0200)
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>
fs/ceph/file.c

index ac75fa9..033e887 100644 (file)
@@ -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);