linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] pstore: fix incorrect persistent ram buffer mapping
@ 2018-09-12  3:36 Bin Yang
  2018-09-12 17:44 ` Kees Cook
  0 siblings, 1 reply; 4+ messages in thread
From: Bin Yang @ 2018-09-12  3:36 UTC (permalink / raw)
  To: keescook, anton, ccross, tony.luck, linux-kernel, bin.yang

persistent_ram_vmap() returns the page start vaddr.
persistent_ram_iomap() supports non-page-aligned mapping.

persistent_ram_buffer_map() always adds offset-in-page to the vaddr
returned from these two functions, which causes incorrect mapping of
non-page-aligned persistent ram buffer.

Signed-off-by: Bin Yang <bin.yang@intel.com>
---
 fs/pstore/ram_core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 951a14e..7c05fdd 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -429,7 +429,7 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
 	vaddr = vmap(pages, page_count, VM_MAP, prot);
 	kfree(pages);
 
-	return vaddr;
+	return vaddr + offset_in_page(start);
 }
 
 static void *persistent_ram_iomap(phys_addr_t start, size_t size,
@@ -468,7 +468,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
 		return -ENOMEM;
 	}
 
-	prz->buffer = prz->vaddr + offset_in_page(start);
+	prz->buffer = prz->vaddr;
 	prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
 
 	return 0;
@@ -515,7 +515,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
 
 	if (prz->vaddr) {
 		if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
-			vunmap(prz->vaddr);
+			vunmap(prz->vaddr - offset_in_page(prz->paddr));
 		} else {
 			iounmap(prz->vaddr);
 			release_mem_region(prz->paddr, prz->size);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] pstore: fix incorrect persistent ram buffer mapping
  2018-09-12  3:36 [PATCH] pstore: fix incorrect persistent ram buffer mapping Bin Yang
@ 2018-09-12 17:44 ` Kees Cook
  2018-09-13  1:21   ` Yang, Bin
  0 siblings, 1 reply; 4+ messages in thread
From: Kees Cook @ 2018-09-12 17:44 UTC (permalink / raw)
  To: Bin Yang; +Cc: Anton Vorontsov, Colin Cross, Tony Luck, LKML

On Tue, Sep 11, 2018 at 8:36 PM, Bin Yang <bin.yang@intel.com> wrote:
> persistent_ram_vmap() returns the page start vaddr.
> persistent_ram_iomap() supports non-page-aligned mapping.

Oh, yes, good catch. This should probably be explicitly mentioned in
comments for these functions.

> persistent_ram_buffer_map() always adds offset-in-page to the vaddr
> returned from these two functions, which causes incorrect mapping of
> non-page-aligned persistent ram buffer.

How did you find this problem, and/or how was the problem manifesting?

> Signed-off-by: Bin Yang <bin.yang@intel.com>
> ---
>  fs/pstore/ram_core.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
> index 951a14e..7c05fdd 100644
> --- a/fs/pstore/ram_core.c
> +++ b/fs/pstore/ram_core.c
> @@ -429,7 +429,7 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
>         vaddr = vmap(pages, page_count, VM_MAP, prot);
>         kfree(pages);
>
> -       return vaddr;
> +       return vaddr + offset_in_page(start);
>  }
>
>  static void *persistent_ram_iomap(phys_addr_t start, size_t size,
> @@ -468,7 +468,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
>                 return -ENOMEM;
>         }
>
> -       prz->buffer = prz->vaddr + offset_in_page(start);
> +       prz->buffer = prz->vaddr;
>         prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
>
>         return 0;
> @@ -515,7 +515,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
>
>         if (prz->vaddr) {
>                 if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
> -                       vunmap(prz->vaddr);
> +                       vunmap(prz->vaddr - offset_in_page(prz->paddr));
>                 } else {
>                         iounmap(prz->vaddr);
>                         release_mem_region(prz->paddr, prz->size);
> --
> 2.7.4
>

Regardless, yes, this patch looks correct. Thanks! I'll add it to my tree.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] pstore: fix incorrect persistent ram buffer mapping
  2018-09-12 17:44 ` Kees Cook
@ 2018-09-13  1:21   ` Yang, Bin
  2018-09-13  4:25     ` Kees Cook
  0 siblings, 1 reply; 4+ messages in thread
From: Yang, Bin @ 2018-09-13  1:21 UTC (permalink / raw)
  To: keescook; +Cc: ccross, Luck, Tony, linux-kernel, anton

On Wed, 2018-09-12 at 10:44 -0700, Kees Cook wrote:
> On Tue, Sep 11, 2018 at 8:36 PM, Bin Yang <bin.yang@intel.com> wrote:
> > persistent_ram_vmap() returns the page start vaddr.
> > persistent_ram_iomap() supports non-page-aligned mapping.
> 
> Oh, yes, good catch. This should probably be explicitly mentioned in
> comments for these functions.
> 
> > persistent_ram_buffer_map() always adds offset-in-page to the vaddr
> > returned from these two functions, which causes incorrect mapping of
> > non-page-aligned persistent ram buffer.
> 
> How did you find this problem, and/or how was the problem manifesting?

By default, ftrace_size is 4096 and max_ftrace_cnt is nr_cpu_ids. The
zone_sz in ramoops_init_przs() is 4096/nr_cpu_ids which might not be
page aligned. If the offset-in-page > 2048, the vaddr will be in next
page. If the next page is not mapped, it will cause kernel panic.

I just wanted to enable this driver on my board and did not change the
default value of ftrace_size. It resulted kernel panic as below:


[    0.074231] BUG: unable to handle kernel paging request at
ffffa19e0081b000
[    0.074498] IP: persistent_ram_new+0x1f8/0x39f
[    0.074651] PGD 272eb7067 P4D 272eb7067 PUD 272eb8067 PMD 2721da067
PTE 0
[    0.074886] Oops: 0000 [#1] PREEMPT SMP NOPTI
[    0.075000] Modules linked in:
[    0.075000] CPU: 0 PID: 1 Comm: swapper/0 Tainted:
G     U          4.14.67-94.pk414-sos #4
[    0.075000] task: ffff96ae32f76040 task.stack: ffff96ae32f78000
[    0.075000] RIP: 0010:persistent_ram_new+0x1f8/0x39f
[    0.075000] RSP: 0000:ffff96ae32f7bc00 EFLAGS: 00010246
[    0.075000] RAX: ffffa19e0081a800 RBX: 0000000000040e43 RCX:
ffffffffb38a7380
[    0.075000] RDX: 0000000080000001 RSI: 0000000000000100 RDI:
00000000ffffffff
[    0.075000] RBP: ffff96ae32f7bc40 R08: ffff96ae32e7b0b0 R09:
0000000000000000
[    0.075000] R10: 0000000000000000 R11: ffff96ae321dd900 R12:
00000000000003f4
[    0.075000] R13: ffff96ae321ddf00 R14: ffffa19e0081b000 R15:
0000000000000000
[    0.075000] FS:  0000000000000000(0000) GS:ffff96ae3fc00000(0000)
knlGS:0000000000000000
[    0.075000] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    0.075000] CR2: ffffa19e0081b000 CR3: 0000000038814000 CR4:
00000000003406f0
[    0.075000] Call Trace:
[    0.075000]  ramoops_init_przs.part.10.constprop.15+0x105/0x260
[    0.075000]  ramoops_probe+0x232/0x3a0
[    0.075000]  platform_drv_probe+0x3e/0xa0
[    0.075000]  driver_probe_device+0x2cd/0x400
[    0.075000]  __driver_attach+0xe4/0x110
[    0.075000]  ? driver_probe_device+0x400/0x400
[    0.075000]  bus_for_each_dev+0x70/0xa0
[    0.075000]  driver_attach+0x1e/0x20
[    0.075000]  bus_add_driver+0x159/0x230
[    0.075000]  ? do_early_param+0x95/0x95
[    0.075000]  driver_register+0x70/0xc0
[    0.075000]  ? init_pstore_fs+0x4d/0x4d
[    0.075000]  __platform_driver_register+0x36/0x40
[    0.075000]  ramoops_init+0x12f/0x131
[    0.075000]  do_one_initcall+0x4d/0x12c
[    0.075000]  ? do_early_param+0x95/0x95
[    0.075000]  kernel_init_freeable+0x19b/0x222
[    0.075000]  ? rest_init+0xbb/0xbb
[    0.075000]  kernel_init+0xe/0xfc
[    0.075000]  ret_from_fork+0x3a/0x50
[    0.075000] Code: 4c 89 f2 49 c7 45 60 00 00 00 00 49 8d 7d 58 e8 af
f6 ff ff 85 c0 89 c3 0f 8f 96 02 00 00 0f 85 ab 02 00 00 4d 8b 75 18 8b
5d cc <41> 8b 16 81 f3 44 42 47 43 39 d3 0f
[    0.075000] RIP: persistent_ram_new+0x1f8/0x39f RSP:
ffff96ae32f7bc00
[    0.075000] CR2: ffffa19e0081b000
[    0.075000] ---[ end trace a92ad58b000ab3fe ]---
[    0.075000] Kernel panic - not syncing: Fatal exception
[    0.075000] reboot: panic mode set: p,w
[    0.075000] Rebooting in 10 seconds..


> 
> > Signed-off-by: Bin Yang <bin.yang@intel.com>
> > ---
> >  fs/pstore/ram_core.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
> > index 951a14e..7c05fdd 100644
> > --- a/fs/pstore/ram_core.c
> > +++ b/fs/pstore/ram_core.c
> > @@ -429,7 +429,7 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
> >         vaddr = vmap(pages, page_count, VM_MAP, prot);
> >         kfree(pages);
> > 
> > -       return vaddr;
> > +       return vaddr + offset_in_page(start);
> >  }
> > 
> >  static void *persistent_ram_iomap(phys_addr_t start, size_t size,
> > @@ -468,7 +468,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
> >                 return -ENOMEM;
> >         }
> > 
> > -       prz->buffer = prz->vaddr + offset_in_page(start);
> > +       prz->buffer = prz->vaddr;
> >         prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
> > 
> >         return 0;
> > @@ -515,7 +515,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
> > 
> >         if (prz->vaddr) {
> >                 if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
> > -                       vunmap(prz->vaddr);
> > +                       vunmap(prz->vaddr - offset_in_page(prz->paddr));
> >                 } else {
> >                         iounmap(prz->vaddr);
> >                         release_mem_region(prz->paddr, prz->size);
> > --
> > 2.7.4
> > 
> 
> Regardless, yes, this patch looks correct. Thanks! I'll add it to my tree.

thanks

> 
> -Kees
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] pstore: fix incorrect persistent ram buffer mapping
  2018-09-13  1:21   ` Yang, Bin
@ 2018-09-13  4:25     ` Kees Cook
  0 siblings, 0 replies; 4+ messages in thread
From: Kees Cook @ 2018-09-13  4:25 UTC (permalink / raw)
  To: Yang, Bin; +Cc: ccross, Luck, Tony, linux-kernel, anton

On Wed, Sep 12, 2018 at 6:21 PM, Yang, Bin <bin.yang@intel.com> wrote:
> On Wed, 2018-09-12 at 10:44 -0700, Kees Cook wrote:
>> On Tue, Sep 11, 2018 at 8:36 PM, Bin Yang <bin.yang@intel.com> wrote:
>> > persistent_ram_vmap() returns the page start vaddr.
>> > persistent_ram_iomap() supports non-page-aligned mapping.
>>
>> Oh, yes, good catch. This should probably be explicitly mentioned in
>> comments for these functions.
>>
>> > persistent_ram_buffer_map() always adds offset-in-page to the vaddr
>> > returned from these two functions, which causes incorrect mapping of
>> > non-page-aligned persistent ram buffer.
>>
>> How did you find this problem, and/or how was the problem manifesting?
>
> By default, ftrace_size is 4096 and max_ftrace_cnt is nr_cpu_ids. The
> zone_sz in ramoops_init_przs() is 4096/nr_cpu_ids which might not be
> page aligned. If the offset-in-page > 2048, the vaddr will be in next
> page. If the next page is not mapped, it will cause kernel panic.
>
> I just wanted to enable this driver on my board and did not change the
> default value of ftrace_size. It resulted kernel panic as below:
>
>
> [    0.074231] BUG: unable to handle kernel paging request at
> ffffa19e0081b000

Perfect, thanks! I've updated your commit log to include these details
now. Should be in linux-next shortly.

-Kees

-- 
Kees Cook
Pixel Security

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-09-13  4:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-12  3:36 [PATCH] pstore: fix incorrect persistent ram buffer mapping Bin Yang
2018-09-12 17:44 ` Kees Cook
2018-09-13  1:21   ` Yang, Bin
2018-09-13  4:25     ` Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).