diff options
author | Alex Elder <elder@inktank.com> | 2012-08-02 11:29:45 -0500 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-10-01 14:30:48 -0500 |
commit | 103a150f0cc57576b1c4b80bf07af60a14349eee (patch) | |
tree | 792d889aa95fe748a7c402b5ac7d6af4c397bb80 /drivers/block | |
parent | 28cb775de1bd1bcc62c43f767ab81b7b9cfb6678 (diff) |
rbd: expand rbd_dev_ondisk_valid() checks
Add checks on the validity of the snap_count and snap_names_len
field values in rbd_dev_ondisk_valid(). This eliminates the
need to do them in rbd_header_from_disk().
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/rbd.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index aff4e8a01ea5..5bcd4ebb22e7 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -481,8 +481,31 @@ static void rbd_coll_release(struct kref *kref) static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) { - return !memcmp(&ondisk->text, - RBD_HEADER_TEXT, sizeof (RBD_HEADER_TEXT)); + size_t size; + u32 snap_count; + + /* The header has to start with the magic rbd header text */ + if (memcmp(&ondisk->text, RBD_HEADER_TEXT, sizeof (RBD_HEADER_TEXT))) + return false; + + /* + * The size of a snapshot header has to fit in a size_t, and + * that limits the number of snapshots. + */ + snap_count = le32_to_cpu(ondisk->snap_count); + size = SIZE_MAX - sizeof (struct ceph_snap_context); + if (snap_count > size / sizeof (__le64)) + return false; + + /* + * Not only that, but the size of the entire the snapshot + * header must also be representable in a size_t. + */ + size -= snap_count * sizeof (__le64); + if ((u64) size < le64_to_cpu(ondisk->snap_names_len)) + return false; + + return true; } /* @@ -499,15 +522,10 @@ static int rbd_header_from_disk(struct rbd_image_header *header, if (!rbd_dev_ondisk_valid(ondisk)) return -ENXIO; - snap_count = le32_to_cpu(ondisk->snap_count); - - /* Make sure we don't overflow below */ - size = SIZE_MAX - sizeof (struct ceph_snap_context); - if (snap_count > size / sizeof (header->snapc->snaps[0])) - return -EINVAL; - memset(header, 0, sizeof (*header)); + snap_count = le32_to_cpu(ondisk->snap_count); + size = sizeof (ondisk->block_name) + 1; header->object_prefix = kmalloc(size, GFP_KERNEL); if (!header->object_prefix) |