diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2016-09-15 12:05:16 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2016-10-03 10:13:49 -0400 |
commit | 04dc923c9e4c43df7d2d94f290189785d3172326 (patch) | |
tree | 1ff276268fd5d3029281e2fa0b31fe2d5d9df053 | |
parent | 7c84883adf6dc614fc9e01304aa1813a55c43ad2 (diff) |
rbd: img_data requests don't own their page array
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>
-rw-r--r-- | drivers/block/rbd.c | 11 |
1 files changed, 3 insertions, 8 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 02e9a0f0bf7b..e46f4f05fb01 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -2147,7 +2147,9 @@ static void rbd_obj_request_destroy(struct kref *kref) | |||
2147 | bio_chain_put(obj_request->bio_list); | 2147 | bio_chain_put(obj_request->bio_list); |
2148 | break; | 2148 | break; |
2149 | case OBJ_REQUEST_PAGES: | 2149 | case OBJ_REQUEST_PAGES: |
2150 | if (obj_request->pages) | 2150 | /* img_data requests don't own their page array */ |
2151 | if (obj_request->pages && | ||
2152 | !obj_request_img_data_test(obj_request)) | ||
2151 | ceph_release_page_vector(obj_request->pages, | 2153 | ceph_release_page_vector(obj_request->pages, |
2152 | obj_request->page_count); | 2154 | obj_request->page_count); |
2153 | break; | 2155 | break; |
@@ -2368,13 +2370,6 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) | |||
2368 | xferred = obj_request->length; | 2370 | xferred = obj_request->length; |
2369 | } | 2371 | } |
2370 | 2372 | ||
2371 | /* Image object requests don't own their page array */ | ||
2372 | |||
2373 | if (obj_request->type == OBJ_REQUEST_PAGES) { | ||
2374 | obj_request->pages = NULL; | ||
2375 | obj_request->page_count = 0; | ||
2376 | } | ||
2377 | |||
2378 | if (img_request_child_test(img_request)) { | 2373 | if (img_request_child_test(img_request)) { |
2379 | rbd_assert(img_request->obj_request != NULL); | 2374 | rbd_assert(img_request->obj_request != NULL); |
2380 | more = obj_request->which < img_request->obj_request_count - 1; | 2375 | more = obj_request->which < img_request->obj_request_count - 1; |