Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit e5a0031

Browse files
Alexander Gordeevgregkh
authored andcommitted
fs/proc/kcore.c: allow translation of physical memory addresses
commit 3d5854d upstream. When /proc/kcore is read an attempt to read the first two pages results in HW-specific page swap on s390 and another (so called prefix) pages are accessed instead. That leads to a wrong read. Allow architecture-specific translation of memory addresses using kc_xlate_dev_mem_ptr() and kc_unxlate_dev_mem_ptr() callbacks similarily to /dev/mem xlate_dev_mem_ptr() and unxlate_dev_mem_ptr() callbacks. That way an architecture can deal with specific physical memory ranges. Re-use the existing /dev/mem callback implementation on s390, which handles the described prefix pages swapping correctly. For other architectures the default callback is basically NOP. It is expected the condition (vaddr == __va(__pa(vaddr))) always holds true for KCORE_RAM memory type. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Alexander Gordeev <[email protected]> Suggested-by: Heiko Carstens <[email protected]> Cc: Vasily Gorbik <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 19a5029 commit e5a0031

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

arch/s390/include/asm/io.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
#include <asm/pci_io.h>
1717

1818
#define xlate_dev_mem_ptr xlate_dev_mem_ptr
19+
#define kc_xlate_dev_mem_ptr xlate_dev_mem_ptr
1920
void *xlate_dev_mem_ptr(phys_addr_t phys);
2021
#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
22+
#define kc_unxlate_dev_mem_ptr unxlate_dev_mem_ptr
2123
void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
2224

2325
#define IO_SPACE_LIMIT 0

fs/proc/kcore.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ static struct proc_dir_entry *proc_root_kcore;
5050
#define kc_offset_to_vaddr(o) ((o) + PAGE_OFFSET)
5151
#endif
5252

53+
#ifndef kc_xlate_dev_mem_ptr
54+
#define kc_xlate_dev_mem_ptr kc_xlate_dev_mem_ptr
55+
static inline void *kc_xlate_dev_mem_ptr(phys_addr_t phys)
56+
{
57+
return __va(phys);
58+
}
59+
#endif
60+
#ifndef kc_unxlate_dev_mem_ptr
61+
#define kc_unxlate_dev_mem_ptr kc_unxlate_dev_mem_ptr
62+
static inline void kc_unxlate_dev_mem_ptr(phys_addr_t phys, void *virt)
63+
{
64+
}
65+
#endif
66+
5367
static LIST_HEAD(kclist_head);
5468
static DECLARE_RWSEM(kclist_lock);
5569
static int kcore_need_update = 1;
@@ -471,6 +485,8 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
471485
while (buflen) {
472486
struct page *page;
473487
unsigned long pfn;
488+
phys_addr_t phys;
489+
void *__start;
474490

475491
/*
476492
* If this is the first iteration or the address is not within
@@ -537,7 +553,8 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
537553
}
538554
break;
539555
case KCORE_RAM:
540-
pfn = __pa(start) >> PAGE_SHIFT;
556+
phys = __pa(start);
557+
pfn = phys >> PAGE_SHIFT;
541558
page = pfn_to_online_page(pfn);
542559

543560
/*
@@ -556,13 +573,28 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
556573
fallthrough;
557574
case KCORE_VMEMMAP:
558575
case KCORE_TEXT:
576+
if (m->type == KCORE_RAM) {
577+
__start = kc_xlate_dev_mem_ptr(phys);
578+
if (!__start) {
579+
ret = -ENOMEM;
580+
if (iov_iter_zero(tsz, iter) != tsz)
581+
ret = -EFAULT;
582+
goto out;
583+
}
584+
} else {
585+
__start = (void *)start;
586+
}
587+
559588
/*
560589
* Sadly we must use a bounce buffer here to be able to
561590
* make use of copy_from_kernel_nofault(), as these
562591
* memory regions might not always be mapped on all
563592
* architectures.
564593
*/
565-
if (copy_from_kernel_nofault(buf, (void *)start, tsz)) {
594+
ret = copy_from_kernel_nofault(buf, __start, tsz);
595+
if (m->type == KCORE_RAM)
596+
kc_unxlate_dev_mem_ptr(phys, __start);
597+
if (ret) {
566598
if (iov_iter_zero(tsz, iter) != tsz) {
567599
ret = -EFAULT;
568600
goto out;

0 commit comments

Comments
 (0)