summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChristophe Leroy <christophe.leroy@c-s.fr>2019-06-24 07:20:14 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-26 09:10:55 +0200
commit8035ba716c3e00610d28a51f4a397886e7e42129 (patch)
tree220867835d8a4dbe80bf5a1114c6bef494062492 /lib
parent3afd8b1e1568a9357ad268fed8d340552c35a81f (diff)
downloadlinux-stable-8035ba716c3e00610d28a51f4a397886e7e42129.tar.gz
linux-stable-8035ba716c3e00610d28a51f4a397886e7e42129.tar.bz2
linux-stable-8035ba716c3e00610d28a51f4a397886e7e42129.zip
lib/scatterlist: Fix mapping iterator when sg->offset is greater than PAGE_SIZE
commit aeb87246537a83c2aff482f3f34a2e0991e02cbc upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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 2882d9ba6607..eacb82468437 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -676,17 +676,18 @@ static bool sg_miter_get_next_page(struct sg_mapping_iter *miter)
{
if (!miter->__remaining) {
struct scatterlist *sg;
- unsigned long pgoffset;
if (!__sg_page_iter_next(&miter->piter))
return false;
sg = miter->piter.sg;
- pgoffset = miter->piter.sg_pgoffset;
- miter->__offset = pgoffset ? 0 : sg->offset;
+ miter->__offset = miter->piter.sg_pgoffset ? 0 : sg->offset;
+ miter->piter.sg_pgoffset += miter->__offset >> PAGE_SHIFT;
+ miter->__offset &= PAGE_SIZE - 1;
miter->__remaining = sg->offset + sg->length -
- (pgoffset << PAGE_SHIFT) - miter->__offset;
+ (miter->piter.sg_pgoffset << PAGE_SHIFT) -
+ miter->__offset;
miter->__remaining = min_t(unsigned long, miter->__remaining,
PAGE_SIZE - miter->__offset);
}