rbd: img_data requests don't own their page array
authorIlya Dryomov <idryomov@gmail.com>
Thu, 15 Sep 2016 16:05:16 +0000 (18:05 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 3 Oct 2016 14:13:49 +0000 (16:13 +0200)
Move the check into rbd_obj_request_destroy() to avoid use-after-free
on errors in rbd_img_request_fill(..., OBJ_REQUEST_PAGES, ...), where
pages, owned by the caller, gets freed in rbd_img_request_fill().

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Alex Elder <elder@linaro.org>
Reviewed-by: David Disseldorp <ddiss@suse.de>
drivers/block/rbd.c

index 02e9a0f..e46f4f0 100644 (file)
@@ -2147,7 +2147,9 @@ static void rbd_obj_request_destroy(struct kref *kref)
                        bio_chain_put(obj_request->bio_list);
                break;
        case OBJ_REQUEST_PAGES:
-               if (obj_request->pages)
+               /* img_data requests don't own their page array */
+               if (obj_request->pages &&
+                   !obj_request_img_data_test(obj_request))
                        ceph_release_page_vector(obj_request->pages,
                                                obj_request->page_count);
                break;
@@ -2368,13 +2370,6 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
                xferred = obj_request->length;
        }
 
-       /* Image object requests don't own their page array */
-
-       if (obj_request->type == OBJ_REQUEST_PAGES) {
-               obj_request->pages = NULL;
-               obj_request->page_count = 0;
-       }
-
        if (img_request_child_test(img_request)) {
                rbd_assert(img_request->obj_request != NULL);
                more = obj_request->which < img_request->obj_request_count - 1;