| From 243409ba79547d237057e03b1343791fd729d51a Mon Sep 17 00:00:00 2001 |
| From: Minchan Kim <minchan@kernel.org> |
| Date: Thu, 13 Apr 2017 14:56:37 -0700 |
| Subject: [PATCH] zram: do not use copy_page with non-page aligned address |
| |
| commit d72e9a7a93e4f8e9e52491921d99e0c8aa89eb4e upstream. |
| |
| The copy_page is optimized memcpy for page-alinged address. If it is |
| used with non-page aligned address, it can corrupt memory which means |
| system corruption. With zram, it can happen with |
| |
| 1. 64K architecture |
| 2. partial IO |
| 3. slub debug |
| |
| Partial IO need to allocate a page and zram allocates it via kmalloc. |
| With slub debug, kmalloc(PAGE_SIZE) doesn't return page-size aligned |
| address. And finally, copy_page(mem, cmem) corrupts memory. |
| |
| So, this patch changes it to memcpy. |
| |
| Actuaully, we don't need to change zram_bvec_write part because zsmalloc |
| returns page-aligned address in case of PAGE_SIZE class but it's not |
| good to rely on the internal of zsmalloc. |
| |
| Note: |
| When this patch is merged to stable, clear_page should be fixed, too. |
| Unfortunately, recent zram removes it by "same page merge" feature so |
| it's hard to backport this patch to -stable tree. |
| |
| I will handle it when I receive the mail from stable tree maintainer to |
| merge this patch to backport. |
| |
| Fixes: 42e99bd ("zram: optimize memory operations with clear_page()/copy_page()") |
| Link: http://lkml.kernel.org/r/1492042622-12074-2-git-send-email-minchan@kernel.org |
| Signed-off-by: Minchan Kim <minchan@kernel.org> |
| Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c |
| index d2ef51ca9cf4..f874e2a529f4 100644 |
| --- a/drivers/block/zram/zram_drv.c |
| +++ b/drivers/block/zram/zram_drv.c |
| @@ -588,7 +588,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) |
| |
| cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); |
| if (size == PAGE_SIZE) { |
| - copy_page(mem, cmem); |
| + memcpy(mem, cmem, PAGE_SIZE); |
| } else { |
| struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp); |
| |
| @@ -780,7 +780,7 @@ compress_again: |
| |
| if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) { |
| src = kmap_atomic(page); |
| - copy_page(cmem, src); |
| + memcpy(cmem, src, PAGE_SIZE); |
| kunmap_atomic(src); |
| } else { |
| memcpy(cmem, src, clen); |
| -- |
| 2.12.0 |
| |