more bio_map_user_iov() leak fixes
commit 2b04e8f6bbb196cab4b232af0f8d48ff2c7a8058 upstream. we need to take care of failure exit as well - pages already in bio should be dropped by analogue of bio_unmap_pages(), since their refcounts had been bumped only once per reference in bio. Cc: stable@vger.kernel.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
3a620404e2
commit
047a7bb12d
14
block/bio.c
14
block/bio.c
|
@ -1268,6 +1268,7 @@ struct bio *bio_map_user_iov(struct request_queue *q,
|
|||
int ret, offset;
|
||||
struct iov_iter i;
|
||||
struct iovec iov;
|
||||
struct bio_vec *bvec;
|
||||
|
||||
iov_for_each(iov, i, *iter) {
|
||||
unsigned long uaddr = (unsigned long) iov.iov_base;
|
||||
|
@ -1312,7 +1313,12 @@ struct bio *bio_map_user_iov(struct request_queue *q,
|
|||
ret = get_user_pages_fast(uaddr, local_nr_pages,
|
||||
(iter->type & WRITE) != WRITE,
|
||||
&pages[cur_page]);
|
||||
if (ret < local_nr_pages) {
|
||||
if (unlikely(ret < local_nr_pages)) {
|
||||
for (j = cur_page; j < page_limit; j++) {
|
||||
if (!pages[j])
|
||||
break;
|
||||
put_page(pages[j]);
|
||||
}
|
||||
ret = -EFAULT;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
@ -1374,10 +1380,8 @@ struct bio *bio_map_user_iov(struct request_queue *q,
|
|||
return bio;
|
||||
|
||||
out_unmap:
|
||||
for (j = 0; j < nr_pages; j++) {
|
||||
if (!pages[j])
|
||||
break;
|
||||
page_cache_release(pages[j]);
|
||||
bio_for_each_segment_all(bvec, bio, j) {
|
||||
put_page(bvec->bv_page);
|
||||
}
|
||||
out:
|
||||
kfree(pages);
|
||||
|
|
Loading…
Reference in New Issue
Block a user