diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-09-14 00:52:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-09-14 00:52:41 -0400 |
commit | 145ea6f10d42dac0a1e8a6dfb83b273c0acabf5b (patch) | |
tree | cac7179f0f523f2f20d9e9cbe1d100d19b6d7bc5 | |
parent | 4624d6ea1b7fe83f1e36caf4537600414ca833f6 (diff) | |
parent | 831b624df1b420c8f9281ed1307a8db23afb72df (diff) |
Merge tag 'pstore-v4.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull pstore fix from Kees Cook:
"This fixes a 6 year old pstore bug that everyone just got lucky in
avoiding, likely due only using page-aligned persistent ram regions:
- Handle page-vs-byte offset handling between iomap and vmap (Bin Yang)"
* tag 'pstore-v4.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
pstore: Fix incorrect persistent ram buffer mapping
-rw-r--r-- | fs/pstore/ram_core.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 951a14edcf51..0792595ebcfb 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c | |||
@@ -429,7 +429,12 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size, | |||
429 | vaddr = vmap(pages, page_count, VM_MAP, prot); | 429 | vaddr = vmap(pages, page_count, VM_MAP, prot); |
430 | kfree(pages); | 430 | kfree(pages); |
431 | 431 | ||
432 | return vaddr; | 432 | /* |
433 | * Since vmap() uses page granularity, we must add the offset | ||
434 | * into the page here, to get the byte granularity address | ||
435 | * into the mapping to represent the actual "start" location. | ||
436 | */ | ||
437 | return vaddr + offset_in_page(start); | ||
433 | } | 438 | } |
434 | 439 | ||
435 | static void *persistent_ram_iomap(phys_addr_t start, size_t size, | 440 | static void *persistent_ram_iomap(phys_addr_t start, size_t size, |
@@ -448,6 +453,11 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size, | |||
448 | else | 453 | else |
449 | va = ioremap_wc(start, size); | 454 | va = ioremap_wc(start, size); |
450 | 455 | ||
456 | /* | ||
457 | * Since request_mem_region() and ioremap() are byte-granularity | ||
458 | * there is no need handle anything special like we do when the | ||
459 | * vmap() case in persistent_ram_vmap() above. | ||
460 | */ | ||
451 | return va; | 461 | return va; |
452 | } | 462 | } |
453 | 463 | ||
@@ -468,7 +478,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, | |||
468 | return -ENOMEM; | 478 | return -ENOMEM; |
469 | } | 479 | } |
470 | 480 | ||
471 | prz->buffer = prz->vaddr + offset_in_page(start); | 481 | prz->buffer = prz->vaddr; |
472 | prz->buffer_size = size - sizeof(struct persistent_ram_buffer); | 482 | prz->buffer_size = size - sizeof(struct persistent_ram_buffer); |
473 | 483 | ||
474 | return 0; | 484 | return 0; |
@@ -515,7 +525,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz) | |||
515 | 525 | ||
516 | if (prz->vaddr) { | 526 | if (prz->vaddr) { |
517 | if (pfn_valid(prz->paddr >> PAGE_SHIFT)) { | 527 | if (pfn_valid(prz->paddr >> PAGE_SHIFT)) { |
518 | vunmap(prz->vaddr); | 528 | /* We must vunmap() at page-granularity. */ |
529 | vunmap(prz->vaddr - offset_in_page(prz->paddr)); | ||
519 | } else { | 530 | } else { |
520 | iounmap(prz->vaddr); | 531 | iounmap(prz->vaddr); |
521 | release_mem_region(prz->paddr, prz->size); | 532 | release_mem_region(prz->paddr, prz->size); |