|
Takashi Iwai |
e36200 |
From 831b624df1b420c8f9281ed1307a8db23afb72df Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
e36200 |
From: Bin Yang <bin.yang@intel.com>
|
|
Takashi Iwai |
e36200 |
Date: Wed, 12 Sep 2018 03:36:34 +0000
|
|
Takashi Iwai |
e36200 |
Subject: [PATCH] pstore: Fix incorrect persistent ram buffer mapping
|
|
Takashi Iwai |
e36200 |
Git-commit: 831b624df1b420c8f9281ed1307a8db23afb72df
|
|
Takashi Iwai |
e36200 |
Patch-mainline: v4.19-rc4
|
|
Takashi Iwai |
e36200 |
References: bsc#1051510
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
persistent_ram_vmap() returns the page start vaddr.
|
|
Takashi Iwai |
e36200 |
persistent_ram_iomap() supports non-page-aligned mapping.
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
persistent_ram_buffer_map() always adds offset-in-page to the vaddr
|
|
Takashi Iwai |
e36200 |
returned from these two functions, which causes incorrect mapping of
|
|
Takashi Iwai |
e36200 |
non-page-aligned persistent ram buffer.
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
By default ftrace_size is 4096 and max_ftrace_cnt is nr_cpu_ids. Without
|
|
Takashi Iwai |
e36200 |
this patch, the zone_sz in ramoops_init_przs() is 4096/nr_cpu_ids which
|
|
Takashi Iwai |
e36200 |
might not be page aligned. If the offset-in-page > 2048, the vaddr will be
|
|
Takashi Iwai |
e36200 |
in next page. If the next page is not mapped, it will cause kernel panic:
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
[ 0.074231] BUG: unable to handle kernel paging request at ffffa19e0081b000
|
|
Takashi Iwai |
e36200 |
...
|
|
Takashi Iwai |
e36200 |
[ 0.075000] RIP: 0010:persistent_ram_new+0x1f8/0x39f
|
|
Takashi Iwai |
e36200 |
...
|
|
Takashi Iwai |
e36200 |
[ 0.075000] Call Trace:
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ramoops_init_przs.part.10.constprop.15+0x105/0x260
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ramoops_probe+0x232/0x3a0
|
|
Takashi Iwai |
e36200 |
[ 0.075000] platform_drv_probe+0x3e/0xa0
|
|
Takashi Iwai |
e36200 |
[ 0.075000] driver_probe_device+0x2cd/0x400
|
|
Takashi Iwai |
e36200 |
[ 0.075000] __driver_attach+0xe4/0x110
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ? driver_probe_device+0x400/0x400
|
|
Takashi Iwai |
e36200 |
[ 0.075000] bus_for_each_dev+0x70/0xa0
|
|
Takashi Iwai |
e36200 |
[ 0.075000] driver_attach+0x1e/0x20
|
|
Takashi Iwai |
e36200 |
[ 0.075000] bus_add_driver+0x159/0x230
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ? do_early_param+0x95/0x95
|
|
Takashi Iwai |
e36200 |
[ 0.075000] driver_register+0x70/0xc0
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ? init_pstore_fs+0x4d/0x4d
|
|
Takashi Iwai |
e36200 |
[ 0.075000] __platform_driver_register+0x36/0x40
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ramoops_init+0x12f/0x131
|
|
Takashi Iwai |
e36200 |
[ 0.075000] do_one_initcall+0x4d/0x12c
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ? do_early_param+0x95/0x95
|
|
Takashi Iwai |
e36200 |
[ 0.075000] kernel_init_freeable+0x19b/0x222
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ? rest_init+0xbb/0xbb
|
|
Takashi Iwai |
e36200 |
[ 0.075000] kernel_init+0xe/0xfc
|
|
Takashi Iwai |
e36200 |
[ 0.075000] ret_from_fork+0x3a/0x50
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
Signed-off-by: Bin Yang <bin.yang@intel.com>
|
|
Takashi Iwai |
e36200 |
[kees: add comments describing the mapping differences, updated commit log]
|
|
Takashi Iwai |
e36200 |
Fixes: 24c3d2f342ed ("staging: android: persistent_ram: Make it possible to use memory outside of bootmem")
|
|
Takashi Iwai |
e36200 |
Cc: stable@vger.kernel.org
|
|
Takashi Iwai |
e36200 |
Signed-off-by: Kees Cook <keescook@chromium.org>
|
|
Takashi Iwai |
e36200 |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
---
|
|
Takashi Iwai |
e36200 |
fs/pstore/ram_core.c | 17 ++++++++++++++---
|
|
Takashi Iwai |
e36200 |
1 file changed, 14 insertions(+), 3 deletions(-)
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
--- a/fs/pstore/ram_core.c
|
|
Takashi Iwai |
e36200 |
+++ b/fs/pstore/ram_core.c
|
|
Takashi Iwai |
e36200 |
@@ -421,7 +421,12 @@ static void *persistent_ram_vmap(phys_ad
|
|
Takashi Iwai |
e36200 |
vaddr = vmap(pages, page_count, VM_MAP, prot);
|
|
Takashi Iwai |
e36200 |
kfree(pages);
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
- return vaddr;
|
|
Takashi Iwai |
e36200 |
+ /*
|
|
Takashi Iwai |
e36200 |
+ * Since vmap() uses page granularity, we must add the offset
|
|
Takashi Iwai |
e36200 |
+ * into the page here, to get the byte granularity address
|
|
Takashi Iwai |
e36200 |
+ * into the mapping to represent the actual "start" location.
|
|
Takashi Iwai |
e36200 |
+ */
|
|
Takashi Iwai |
e36200 |
+ return vaddr + offset_in_page(start);
|
|
Takashi Iwai |
e36200 |
}
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
static void *persistent_ram_iomap(phys_addr_t start, size_t size,
|
|
Takashi Iwai |
e36200 |
@@ -440,6 +445,11 @@ static void *persistent_ram_iomap(phys_a
|
|
Takashi Iwai |
e36200 |
else
|
|
Takashi Iwai |
e36200 |
va = ioremap_wc(start, size);
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
+ /*
|
|
Takashi Iwai |
e36200 |
+ * Since request_mem_region() and ioremap() are byte-granularity
|
|
Takashi Iwai |
e36200 |
+ * there is no need handle anything special like we do when the
|
|
Takashi Iwai |
e36200 |
+ * vmap() case in persistent_ram_vmap() above.
|
|
Takashi Iwai |
e36200 |
+ */
|
|
Takashi Iwai |
e36200 |
return va;
|
|
Takashi Iwai |
e36200 |
}
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
@@ -460,7 +470,7 @@ static int persistent_ram_buffer_map(phy
|
|
Takashi Iwai |
e36200 |
return -ENOMEM;
|
|
Takashi Iwai |
e36200 |
}
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
- prz->buffer = prz->vaddr + offset_in_page(start);
|
|
Takashi Iwai |
e36200 |
+ prz->buffer = prz->vaddr;
|
|
Takashi Iwai |
e36200 |
prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
return 0;
|
|
Takashi Iwai |
e36200 |
@@ -507,7 +517,8 @@ void persistent_ram_free(struct persiste
|
|
Takashi Iwai |
e36200 |
|
|
Takashi Iwai |
e36200 |
if (prz->vaddr) {
|
|
Takashi Iwai |
e36200 |
if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
|
|
Takashi Iwai |
e36200 |
- vunmap(prz->vaddr);
|
|
Takashi Iwai |
e36200 |
+ /* We must vunmap() at page-granularity. */
|
|
Takashi Iwai |
e36200 |
+ vunmap(prz->vaddr - offset_in_page(prz->paddr));
|
|
Takashi Iwai |
e36200 |
} else {
|
|
Takashi Iwai |
e36200 |
iounmap(prz->vaddr);
|
|
Takashi Iwai |
e36200 |
release_mem_region(prz->paddr, prz->size);
|