summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/block/rbd.c60
1 files changed, 33 insertions, 27 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 91b4b741efda..44dcc82770d9 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2642,7 +2642,7 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev,
* method. Currently if this is present it will be a
* snapshot id.
*/
- page_count = (u32) calc_pages_for(0, inbound_size);
+ page_count = (u32)calc_pages_for(0, inbound_size);
pages = ceph_alloc_page_vector(page_count, GFP_KERNEL);
if (IS_ERR(pages))
return PTR_ERR(pages);
@@ -2689,7 +2689,9 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev,
ret = obj_request->result;
if (ret < 0)
goto out;
- ret = 0;
+
+ rbd_assert(obj_request->xferred < (u64)INT_MAX);
+ ret = (int)obj_request->xferred;
ceph_copy_from_page_vector(pages, inbound, 0, obj_request->xferred);
if (version)
*version = obj_request->version;
@@ -3583,13 +3585,15 @@ static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
if (ret < 0)
return ret;
+ if (ret < sizeof (size_buf))
+ return -ERANGE;
*order = size_buf.order;
*snap_size = le64_to_cpu(size_buf.size);
dout(" snap_id 0x%016llx order = %u, snap_size = %llu\n",
- (unsigned long long) snap_id, (unsigned int) *order,
- (unsigned long long) *snap_size);
+ (unsigned long long)snap_id, (unsigned int)*order,
+ (unsigned long long)*snap_size);
return 0;
}
@@ -3620,8 +3624,8 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
p = reply_buf;
rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p,
- p + RBD_OBJ_PREFIX_LEN_MAX,
- NULL, GFP_NOIO);
+ p + ret, NULL, GFP_NOIO);
+ ret = 0;
if (IS_ERR(rbd_dev->header.object_prefix)) {
ret = PTR_ERR(rbd_dev->header.object_prefix);
@@ -3629,7 +3633,6 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
} else {
dout(" object_prefix = %s\n", rbd_dev->header.object_prefix);
}
-
out:
kfree(reply_buf);
@@ -3654,6 +3657,8 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
if (ret < 0)
return ret;
+ if (ret < sizeof (features_buf))
+ return -ERANGE;
incompat = le64_to_cpu(features_buf.incompat);
if (incompat & ~RBD_FEATURES_SUPPORTED)
@@ -3662,9 +3667,9 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id,
*snap_features = le64_to_cpu(features_buf.features);
dout(" snap_id 0x%016llx features = 0x%016llx incompat = 0x%016llx\n",
- (unsigned long long) snap_id,
- (unsigned long long) *snap_features,
- (unsigned long long) le64_to_cpu(features_buf.incompat));
+ (unsigned long long)snap_id,
+ (unsigned long long)*snap_features,
+ (unsigned long long)le64_to_cpu(features_buf.incompat));
return 0;
}
@@ -3710,9 +3715,9 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
if (ret < 0)
goto out_err;
- ret = -ERANGE;
p = reply_buf;
- end = reply_buf + size;
+ end = reply_buf + ret;
+ ret = -ERANGE;
ceph_decode_64_safe(&p, end, parent_spec->pool_id, out_err);
if (parent_spec->pool_id == CEPH_NOPOOL)
goto out; /* No parent? No problem. */
@@ -3720,8 +3725,8 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
/* The ceph file layout needs to fit pool id in 32 bits */
ret = -EIO;
- if (WARN_ON(parent_spec->pool_id > (u64) U32_MAX))
- goto out;
+ if (WARN_ON(parent_spec->pool_id > (u64)U32_MAX))
+ goto out_err;
image_id = ceph_extract_encoded_string(&p, end, NULL, GFP_KERNEL);
if (IS_ERR(image_id)) {
@@ -3766,7 +3771,7 @@ static char *rbd_dev_image_name(struct rbd_device *rbd_dev)
p = image_id;
end = image_id + image_id_size;
- ceph_encode_string(&p, end, rbd_dev->spec->image_id, (u32) len);
+ ceph_encode_string(&p, end, rbd_dev->spec->image_id, (u32)len);
size = sizeof (__le32) + RBD_IMAGE_NAME_LEN_MAX;
reply_buf = kmalloc(size, GFP_KERNEL);
@@ -3886,9 +3891,9 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver)
if (ret < 0)
goto out;
- ret = -ERANGE;
p = reply_buf;
- end = reply_buf + size;
+ end = reply_buf + ret;
+ ret = -ERANGE;
ceph_decode_64_safe(&p, end, seq, out);
ceph_decode_32_safe(&p, end, snap_count, out);
@@ -3913,6 +3918,7 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver)
ret = -ENOMEM;
goto out;
}
+ ret = 0;
atomic_set(&snapc->nref, 1);
snapc->seq = seq;
@@ -3923,12 +3929,11 @@ static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver)
rbd_dev->header.snapc = snapc;
dout(" snap context seq = %llu, snap_count = %u\n",
- (unsigned long long) seq, (unsigned int) snap_count);
-
+ (unsigned long long)seq, (unsigned int)snap_count);
out:
kfree(reply_buf);
- return 0;
+ return ret;
}
static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which)
@@ -3963,7 +3968,7 @@ static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which)
goto out;
} else {
dout(" snap_id 0x%016llx snap_name = %s\n",
- (unsigned long long) le64_to_cpu(snap_id), snap_name);
+ (unsigned long long)le64_to_cpu(snap_id), snap_name);
}
kfree(reply_buf);
@@ -4560,8 +4565,10 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
p = response;
rbd_dev->spec->image_id = ceph_extract_encoded_string(&p,
- p + RBD_IMAGE_ID_LEN_MAX,
+ p + ret,
NULL, GFP_NOIO);
+ ret = 0;
+
if (IS_ERR(rbd_dev->spec->image_id)) {
ret = PTR_ERR(rbd_dev->spec->image_id);
rbd_dev->spec->image_id = NULL;
@@ -4642,28 +4649,27 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
RBD_HEADER_PREFIX, rbd_dev->spec->image_id);
/* Get the size and object order for the image */
-
ret = rbd_dev_v2_image_size(rbd_dev);
- if (ret < 0)
+ if (ret)
goto out_err;
/* Get the object prefix (a.k.a. block_name) for the image */
ret = rbd_dev_v2_object_prefix(rbd_dev);
- if (ret < 0)
+ if (ret)
goto out_err;
/* Get the and check features for the image */
ret = rbd_dev_v2_features(rbd_dev);
- if (ret < 0)
+ if (ret)
goto out_err;
/* If the image supports layering, get the parent info */
if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
ret = rbd_dev_v2_parent_info(rbd_dev);
- if (ret < 0)
+ if (ret)
goto out_err;
}