Re: [PATCH 10/11] rbd: check for overflow in rbd_get_num_segments()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Reviewed-by: Yehuda Sadeh <yehuda@xxxxxxxxxxx>

On Fri, Aug 24, 2012 at 9:36 AM, Alex Elder <elder@xxxxxxxxxxx> wrote:
> It is possible in rbd_get_num_segments() for an overflow to occur
> when adding the offset and length.  This is easily avoided.
>
> Since the function returns an int and the one caller is already
> prepared to handle errors, have it return -ERANGE if overflow would
> occur.
>
> The overflow check would not work if a zero-length request was
> being tested, so short-circuit that case, returning 0 for the
> number of segments required.  (This condition might be avoided
> elsewhere already, I don't know.)
>
> Have the caller end the request if either an error or 0 is returned.
> The returned value is passed to __blk_end_request_all(), meaning
> a 0 length request is not treated an error.
>
> Signed-off-by: Alex Elder <elder@xxxxxxxxxxx>
> ---
>  drivers/block/rbd.c |   23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index fad4ecb..b649446 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -50,6 +50,10 @@
>  #define        SECTOR_SHIFT    9
>  #define        SECTOR_SIZE     (1ULL << SECTOR_SHIFT)
>
> +/* It might be useful to have this defined elsewhere too */
> +
> +#define        U64_MAX ((u64) (~0ULL))

ULLONG_MAX defined in include/linux/kernel.h

> +
>  #define RBD_DRV_NAME "rbd"
>  #define RBD_DRV_NAME_LONG "rbd (rados block device)"
>
> @@ -678,8 +682,17 @@ static u64 rbd_get_segment(struct rbd_image_header
> *header,
>  static int rbd_get_num_segments(struct rbd_image_header *header,
>                                 u64 ofs, u64 len)
>  {
> -       u64 start_seg = ofs >> header->obj_order;
> -       u64 end_seg = (ofs + len - 1) >> header->obj_order;
> +       u64 start_seg;
> +       u64 end_seg;
> +
> +       if (!len)
> +               return 0;
> +       if (len - 1 > U64_MAX - ofs)
> +               return -ERANGE;
> +
> +       start_seg = ofs >> header->obj_order;
> +       end_seg = (ofs + len - 1) >> header->obj_order;
> +
>         return end_seg - start_seg + 1;
>  }
>
> @@ -1502,6 +1515,12 @@ static void rbd_rq_fn(struct request_queue *q)
>                      size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE);
>
>                 num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size);
> +               if (num_segs <= 0) {
> +                       spin_lock_irq(q->queue_lock);
> +                       __blk_end_request_all(rq, num_segs);
> +                       ceph_put_snap_context(snapc);
> +                       continue;
> +               }
>                 coll = rbd_alloc_coll(num_segs);
>                 if (!coll) {
>                         spin_lock_irq(q->queue_lock);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux