aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChristophe Leroy <christophe.leroy@c-s.fr>2019-06-24 03:20:14 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-07-03 10:13:11 -0400
commitaeb87246537a83c2aff482f3f34a2e0991e02cbc (patch)
tree9425c5d4b9b8e7f6176b7c705293ef4607498178 /lib
parente52d484d9869eb291140545746ccbe5ffc7c9306 (diff)
lib/scatterlist: Fix mapping iterator when sg->offset is greater than PAGE_SIZE
All mapping iterator logic is based on the assumption that sg->offset is always lower than PAGE_SIZE. But there are situations where sg->offset is such that the SG item is on the second page. In that case sg_copy_to_buffer() fails properly copying the data into the buffer. One of the reason is that the data will be outside the kmapped area used to access that data. This patch fixes the issue by adjusting the mapping iterator offset and pgoffset fields such that offset is always lower than PAGE_SIZE. Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Fixes: 4225fc8555a9 ("lib/scatterlist: use page iterator in the mapping iterator") Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib')
-rw-r--r--lib/scatterlist.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 739dc9fe2c55..f0757a67affe 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -678,17 +678,18 @@ static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
678{ 678{
679 if (!miter->__remaining) { 679 if (!miter->__remaining) {
680 struct scatterlist *sg; 680 struct scatterlist *sg;
681 unsigned long pgoffset;
682 681
683 if (!__sg_page_iter_next(&miter->piter)) 682 if (!__sg_page_iter_next(&miter->piter))
684 return false; 683 return false;
685 684
686 sg = miter->piter.sg; 685 sg = miter->piter.sg;
687 pgoffset = miter->piter.sg_pgoffset;
688 686
689 miter->__offset = pgoffset ? 0 : sg->offset; 687 miter->__offset = miter->piter.sg_pgoffset ? 0 : sg->offset;
688 miter->piter.sg_pgoffset += miter->__offset >> PAGE_SHIFT;
689 miter->__offset &= PAGE_SIZE - 1;
690 miter->__remaining = sg->offset + sg->length - 690 miter->__remaining = sg->offset + sg->length -
691 (pgoffset << PAGE_SHIFT) - miter->__offset; 691 (miter->piter.sg_pgoffset << PAGE_SHIFT) -
692 miter->__offset;
692 miter->__remaining = min_t(unsigned long, miter->__remaining, 693 miter->__remaining = min_t(unsigned long, miter->__remaining,
693 PAGE_SIZE - miter->__offset); 694 PAGE_SIZE - miter->__offset);
694 } 695 }