From: Junxiao Bi <junxiao.bi@oracle.com>
To: linux-kernel@vger.kernel.org
Cc: axboe@kernel.dk, joe.jin@oracle.com
Subject: Re: [PATCH] block: fix uint overflow when merging io requests
Date: Tue, 01 Jul 2014 10:07:31 +0800 [thread overview]
Message-ID: <53B217E3.2090100@oracle.com> (raw)
In-Reply-To: <1403853862-16565-1-git-send-email-junxiao.bi@oracle.com>
On 06/27/2014 03:24 PM, Junxiao Bi wrote:
> This uint overflow will cause req->__data_len < req->bio->bi_size,
> this will confuse block layer and device driver.
>
> I watched a panic caused by this when mkfs.ext4 a volume of a large
> virtual disk on vm guest, blkdev_issue_discard() issue two bio with
> a total size over UINT_MAX, but the check in ll_back_merge_fn() didn't
> take affect due to the overflow and they were merged into one request.
> After the request is done, in blk_end_request_all(), BUG_ON(pending)
> was triggered and kernel panic. "pending" is true is because
> blk_update_request() return ture when req->__data_len is less
> than req->bio->bi_size.
Any body help review this patch?
blk_rq_sectors(), bio_sectors(), blk_rq_get_max_sectors() are all uint.
blk_rq_sectors(req) + bio_sectors(bio) > blk_rq_get_max_sectors(req)
This checking is bypassed when overflow happen. It will cause an io
request's
length less than its child bio's size.
Thanks,
Junxiao.
>
> Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com>
> ---
> block/blk-merge.c | 40 ++++++++++++++++++++++++++++++++++------
> 1 file changed, 34 insertions(+), 6 deletions(-)
>
> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index b3bf0df..340c0a7 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -325,11 +325,41 @@ no_merge:
> return 0;
> }
>
> -int ll_back_merge_fn(struct request_queue *q, struct request *req,
> +static inline bool ll_allow_merge_bio(struct request *req,
> struct bio *bio)
> {
> if (blk_rq_sectors(req) + bio_sectors(bio) >
> - blk_rq_get_max_sectors(req)) {
> + blk_rq_get_max_sectors(req))
> + return false;
> +
> + /* check uint overflow */
> + if (blk_rq_sectors(req) + bio_sectors(bio) < blk_rq_sectors(req)
> + || blk_rq_sectors(req) + bio_sectors(bio) < bio_sectors(bio))
> + return false;
> +
> + return true;
> +}
> +
> +static inline bool ll_allow_merge_req(struct request *req,
> + struct request *next)
> +{
> + if (blk_rq_sectors(req) + blk_rq_sectors(next) >
> + blk_rq_get_max_sectors(req))
> + return false;
> +
> + /* check uint overflow */
> + if (blk_rq_sectors(req) + blk_rq_sectors(next) < blk_rq_sectors(req)
> + || blk_rq_sectors(req) + blk_rq_sectors(next) <
> + blk_rq_sectors(next))
> + return false;
> +
> + return true;
> +}
> +
> +int ll_back_merge_fn(struct request_queue *q, struct request *req,
> + struct bio *bio)
> +{
> + if (!ll_allow_merge_bio(req, bio)) {
> req->cmd_flags |= REQ_NOMERGE;
> if (req == q->last_merge)
> q->last_merge = NULL;
> @@ -346,8 +376,7 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
> int ll_front_merge_fn(struct request_queue *q, struct request *req,
> struct bio *bio)
> {
> - if (blk_rq_sectors(req) + bio_sectors(bio) >
> - blk_rq_get_max_sectors(req)) {
> + if (!ll_allow_merge_bio(req, bio)) {
> req->cmd_flags |= REQ_NOMERGE;
> if (req == q->last_merge)
> q->last_merge = NULL;
> @@ -389,8 +418,7 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
> /*
> * Will it become too large?
> */
> - if ((blk_rq_sectors(req) + blk_rq_sectors(next)) >
> - blk_rq_get_max_sectors(req))
> + if (!ll_allow_merge_req(req, next))
> return 0;
>
> total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
prev parent reply other threads:[~2014-07-01 2:07 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-27 7:24 [PATCH] block: fix uint overflow when merging io requests Junxiao Bi
2014-07-01 2:07 ` Junxiao Bi [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53B217E3.2090100@oracle.com \
--to=junxiao.bi@oracle.com \
--cc=axboe@kernel.dk \
--cc=joe.jin@oracle.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.