mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 13:43:51 +00:00
[SCSI] block: fix bio_add_page misuse with rq_map_data
This fixes bio_add_page misuse in bio_copy_user_iov with rq_map_data, which only sg uses now. rq_map_data carries page frames for bio_add_pc_page. bio_copy_user_iov uses bio_add_pc_page with a larger size than PAGE_SIZE. It's clearly wrong. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Acked-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
4f10aae0d1
commit
e623ddb4e9
26
fs/bio.c
26
fs/bio.c
@ -815,28 +815,30 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
if (map_data)
|
||||||
|
nr_pages = 1 << map_data->page_order;
|
||||||
while (len) {
|
while (len) {
|
||||||
unsigned int bytes;
|
unsigned int bytes = PAGE_SIZE;
|
||||||
|
|
||||||
if (map_data)
|
|
||||||
bytes = 1U << (PAGE_SHIFT + map_data->page_order);
|
|
||||||
else
|
|
||||||
bytes = PAGE_SIZE;
|
|
||||||
|
|
||||||
if (bytes > len)
|
if (bytes > len)
|
||||||
bytes = len;
|
bytes = len;
|
||||||
|
|
||||||
if (map_data) {
|
if (map_data) {
|
||||||
if (i == map_data->nr_entries) {
|
if (i == map_data->nr_entries * nr_pages) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
page = map_data->pages[i++];
|
|
||||||
} else
|
page = map_data->pages[i / nr_pages];
|
||||||
|
page += (i % nr_pages);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
page = alloc_page(q->bounce_gfp | gfp_mask);
|
page = alloc_page(q->bounce_gfp | gfp_mask);
|
||||||
if (!page) {
|
if (!page) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
|
if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)
|
||||||
|
Loading…
Reference in New Issue
Block a user