Message ID | 1554346681-31163-1-git-send-email-lirongqing@baidu.com (mailing list archive) |
---|---|
State | Mainlined |
Commit | 9dc6488e84b0f64df17672271664752488cd6a25 |
Headers | show |
Series | libnvdimm, pmem: fix a possible OOB access when read and write pmem | expand |
On Thu, Apr 04, 2019 at 10:58:01AM +0800, Li RongQing wrote: > If offset is not zero and length is bigger than PAGE_SIZE, > this will cause to out of boundary access to a page memory > > Fixes: 98cc093cba1e "(block, THP: make block_device_operations.rw_page support THP)" > Co-developed-by: Liang ZhiCheng <liangzhicheng@baidu.com> > Signed-off-by: Liang ZhiCheng <liangzhicheng@baidu.com> > Signed-off-by: Li RongQing <lirongqing@baidu.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> > --- > drivers/nvdimm/pmem.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c > index bc2f700feef8..0279eb1da3ef 100644 > --- a/drivers/nvdimm/pmem.c > +++ b/drivers/nvdimm/pmem.c > @@ -113,13 +113,13 @@ static void write_pmem(void *pmem_addr, struct page *page, > > while (len) { > mem = kmap_atomic(page); > - chunk = min_t(unsigned int, len, PAGE_SIZE); > + chunk = min_t(unsigned int, len, PAGE_SIZE - off); > memcpy_flushcache(pmem_addr, mem + off, chunk); > kunmap_atomic(mem); > len -= chunk; > off = 0; > page++; > - pmem_addr += PAGE_SIZE; > + pmem_addr += chunk; > } > } > > @@ -132,7 +132,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, > > while (len) { > mem = kmap_atomic(page); > - chunk = min_t(unsigned int, len, PAGE_SIZE); > + chunk = min_t(unsigned int, len, PAGE_SIZE - off); > rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); > kunmap_atomic(mem); > if (rem) > @@ -140,7 +140,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, > len -= chunk; > off = 0; > page++; > - pmem_addr += PAGE_SIZE; > + pmem_addr += chunk; > } > return BLK_STS_OK; > } > -- > 2.16.2 >
Li RongQing <lirongqing@baidu.com> writes: > If offset is not zero and length is bigger than PAGE_SIZE, > this will cause to out of boundary access to a page memory Agreed, though I don't think this can be triggered in practice. > Fixes: 98cc093cba1e "(block, THP: make block_device_operations.rw_page support THP)" > Co-developed-by: Liang ZhiCheng <liangzhicheng@baidu.com> > Signed-off-by: Liang ZhiCheng <liangzhicheng@baidu.com> > Signed-off-by: Li RongQing <lirongqing@baidu.com> Reviewed-by: Jeff Moyer <jmoyer@redhat.com> > --- > drivers/nvdimm/pmem.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c > index bc2f700feef8..0279eb1da3ef 100644 > --- a/drivers/nvdimm/pmem.c > +++ b/drivers/nvdimm/pmem.c > @@ -113,13 +113,13 @@ static void write_pmem(void *pmem_addr, struct page *page, > > while (len) { > mem = kmap_atomic(page); > - chunk = min_t(unsigned int, len, PAGE_SIZE); > + chunk = min_t(unsigned int, len, PAGE_SIZE - off); > memcpy_flushcache(pmem_addr, mem + off, chunk); > kunmap_atomic(mem); > len -= chunk; > off = 0; > page++; > - pmem_addr += PAGE_SIZE; > + pmem_addr += chunk; > } > } > > @@ -132,7 +132,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, > > while (len) { > mem = kmap_atomic(page); > - chunk = min_t(unsigned int, len, PAGE_SIZE); > + chunk = min_t(unsigned int, len, PAGE_SIZE - off); > rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); > kunmap_atomic(mem); > if (rem) > @@ -140,7 +140,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, > len -= chunk; > off = 0; > page++; > - pmem_addr += PAGE_SIZE; > + pmem_addr += chunk; > } > return BLK_STS_OK; > }
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index bc2f700feef8..0279eb1da3ef 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -113,13 +113,13 @@ static void write_pmem(void *pmem_addr, struct page *page, while (len) { mem = kmap_atomic(page); - chunk = min_t(unsigned int, len, PAGE_SIZE); + chunk = min_t(unsigned int, len, PAGE_SIZE - off); memcpy_flushcache(pmem_addr, mem + off, chunk); kunmap_atomic(mem); len -= chunk; off = 0; page++; - pmem_addr += PAGE_SIZE; + pmem_addr += chunk; } } @@ -132,7 +132,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, while (len) { mem = kmap_atomic(page); - chunk = min_t(unsigned int, len, PAGE_SIZE); + chunk = min_t(unsigned int, len, PAGE_SIZE - off); rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); kunmap_atomic(mem); if (rem) @@ -140,7 +140,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, len -= chunk; off = 0; page++; - pmem_addr += PAGE_SIZE; + pmem_addr += chunk; } return BLK_STS_OK; }