From: Al Viro Date: Sun, 24 Sep 2017 17:09:18 +0000 (-0400) Subject: bio_copy_user_iov(): saner bio size calculation X-Git-Tag: v4.15-rc1~68^2~11 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=d16d44ebb016792285ec1b9566dbd9d022ce70f9;p=linux.git bio_copy_user_iov(): saner bio size calculation it's a bounce buffer; we don't *care* how badly is the real source/destination fragmented, all that matters is the total size. Signed-off-by: Al Viro --- diff --git a/block/bio.c b/block/bio.c index 28f66e2edc53..e87f70cd528e 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1201,33 +1201,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q, struct bio_map_data *bmd; struct page *page; struct bio *bio; - int i, ret; - int nr_pages = 0; + int i = 0, ret; + int nr_pages; unsigned int len = iter->count; unsigned int offset = map_data ? offset_in_page(map_data->offset) : 0; - for (i = 0; i < iter->nr_segs; i++) { - unsigned long uaddr; - unsigned long end; - unsigned long start; - - uaddr = (unsigned long) iter->iov[i].iov_base; - end = (uaddr + iter->iov[i].iov_len + PAGE_SIZE - 1) - >> PAGE_SHIFT; - start = uaddr >> PAGE_SHIFT; - - /* - * Overflow, abort - */ - if (end < start) - return ERR_PTR(-EINVAL); - - nr_pages += end - start; - } - - if (offset) - nr_pages++; - bmd = bio_alloc_map_data(iter->nr_segs, gfp_mask); if (!bmd) return ERR_PTR(-ENOMEM); @@ -1242,6 +1220,10 @@ struct bio *bio_copy_user_iov(struct request_queue *q, bmd->iter = *iter; bmd->iter.iov = bmd->iov; + nr_pages = DIV_ROUND_UP(offset + len, PAGE_SIZE); + if (nr_pages > BIO_MAX_PAGES) + nr_pages = BIO_MAX_PAGES; + ret = -ENOMEM; bio = bio_kmalloc(gfp_mask, nr_pages); if (!bio)