* [PATCH v3] mm: Fix mremap not considering huge pmd devmap
@ 2020-06-04 10:22 Fan Yang
2020-06-04 18:23 ` Ajay Kaher
0 siblings, 1 reply; 4+ messages in thread
From: Fan Yang @ 2020-06-04 10:22 UTC (permalink / raw)
To: linux-kernel; +Cc: Williams, Dan J, Kirill A. Shutemov, Linus Torvalds
The original code in mm/mremap.c checks huge pmd by:
if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd)) {
However, a DAX mapped nvdimm is mapped as huge page (by default) but
it is not transparent huge page (_PAGE_PSE | PAGE_DEVMAP). This
commit changes the condition to include the case.
This addresses CVE-2020-10757.
Fixes: 5c7fb56e5e3f ("mm, dax: dax-pmd vs thp-pmd vs hugetlbfs-pmd")
Cc: <stable@vger.kernel.org>
Reported-by: Fan Yang <Fan_Yang@sjtu.edu.cn>
Signed-off-by: Fan Yang <Fan_Yang@sjtu.edu.cn>
Tested-by: Fan Yang <Fan_Yang@sjtu.edu.cn>
Tested-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
Changelog v2->v3:
- Added "Acked-by: Kirill..."
Changelog v1->v2:
- Removed some paragraph in commit msg, removed the comment in
mm/mremap.c, and added a NOTE in where pmd_trans_huge is defined.
- Added "Reviewed-by: Dan..."
- Added "Fixes: 5c7fb56e5e3f..."
- Added "Cc: <stable@vger.kernel.org>"
---
arch/x86/include/asm/pgtable.h | 1 +
mm/mremap.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 4d02e64af1b3..19cdeebfbde6 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -257,6 +257,7 @@ static inline int pmd_large(pmd_t pte)
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+/* NOTE: when predicate huge page, consider also pmd_devmap, or use pmd_large */
static inline int pmd_trans_huge(pmd_t pmd)
{
return (pmd_val(pmd) & (_PAGE_PSE|_PAGE_DEVMAP)) == _PAGE_PSE;
diff --git a/mm/mremap.c b/mm/mremap.c
index 6aa6ea605068..57b1f999f789 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -266,7 +266,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
new_pmd = alloc_new_pmd(vma->vm_mm, vma, new_addr);
if (!new_pmd)
break;
- if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd)) {
+ if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd) || pmd_devmap(*old_pmd)) {
if (extent == HPAGE_PMD_SIZE) {
bool moved;
/* See comment in move_ptes() */
--
2.25.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3] mm: Fix mremap not considering huge pmd devmap
2020-06-04 10:22 [PATCH v3] mm: Fix mremap not considering huge pmd devmap Fan Yang
@ 2020-06-04 18:23 ` Ajay Kaher
2020-06-05 5:09 ` Fan Yang
0 siblings, 1 reply; 4+ messages in thread
From: Ajay Kaher @ 2020-06-04 18:23 UTC (permalink / raw)
To: fan_yang
Cc: dan.j.williams, kirill.shutemov, linux-kernel, torvalds, gregkh,
srivatsab, srivatsa, akaher
Hi Fan,
Able to reproduce this issue on v4.19.y using your test program.
And as per commit message it fixes commit 5c7fb56e5e3f
("mm, dax: dax-pmd vs thp-pmd vs hugetlbfs-pm”) at kernel version v4.5.
So, v4.9.y should be vulnerable, however not able to reproduce on v4.9.y.
Does any specific scenerio need to test for v4.9.y?
For v4.9, modified test program as MAP_SHARED_VALIDATE is not available:
- return mmap(NULL, REGION_PM_SIZE, PROT, MAP_SHARED_VALIDATE|MAP_SYNC,
+ return mmap(NULL, REGION_PM_SIZE, PROT, MAP_SHARED|MAP_SYNC,
Let me know if I need to test some other way for v4.9.y.
-Ajay
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] mm: Fix mremap not considering huge pmd devmap
2020-06-04 18:23 ` Ajay Kaher
@ 2020-06-05 5:09 ` Fan Yang
2020-06-05 19:14 ` Ajay Kaher
0 siblings, 1 reply; 4+ messages in thread
From: Fan Yang @ 2020-06-05 5:09 UTC (permalink / raw)
To: Ajay Kaher
Cc: Williams, Dan J, Kirill A. Shutemov, linux-kernel,
Linus Torvalds, gregkh, srivatsab, srivatsa
Hi Ajay,
> On Jun 5, 2020 at 02:23,Ajay Kaher <akaher@vmware.com> wrote:
>
> So, v4.9.y should be vulnerable, however not able to reproduce on v4.9.y.
> Does any specific scenerio need to test for v4.9.y?
>
> For v4.9, modified test program as MAP_SHARED_VALIDATE is not available:
> - return mmap(NULL, REGION_PM_SIZE, PROT, MAP_SHARED_VALIDATE|MAP_SYNC,
> + return mmap(NULL, REGION_PM_SIZE, PROT, MAP_SHARED|MAP_SYNC,
>
> Let me know if I need to test some other way for v4.9.y.
>
I further looked into this. In v4.9, fsdax (mount a dax file
system, then open, mmap, mremap) does not suffer this issue
because fsdax does not use huge page (FS_DAX_PMD is marked
BROKEN).
fs/dax.c:dax_pmd_fault:
if (!IS_ENABLED(CONFIG_FS_DAX_PMD))
return VM_FAULT_FALLBACK;
fs/Kconfig:
config FS_DAX_PMD
bool
default FS_DAX
depends on FS_DAX
depends on ZONE_DEVICE
depends on TRANSPARENT_HUGEPAGE
depends on BROKEN
However, I can re-produce the issue for the devdax mode. Here is how
I re-produce it:
1. It seems some interface changed for ndctl. So I use an old
commit (4295f1ea614a26e1304ed590fb7209c8c78270ab) in the repo
https://github.com/pmem/ndctl.
2. sudo ./ndctl/ndctl create-namespace -f -t pmem -m dax -e 'namespace0.0'
3. then use the following program:
#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#define PROT PROT_READ|PROT_WRITE
#define REGION_PM_TMP_PATH "/dev/dax0.0"
#define REGION_MEM_SIZE 1024ULL*1024*1024*2
#define REGION_PM_SIZE 1024ULL*1024*1024*4
#define REMAP_MEM_OFF 1024ULL*1024*1024*1
#define REMAP_PM_OFF 1024ULL*1024*1024*3
#define REMAP_SIZE 1024ULL*1024*1024*1
#define REGION_MEM_PTR ((void *)0x7fd400000000ULL)
#define REGION_PM_PTR ((void *)0x4fd300000000ULL)
char * map_tmp_pm_region(void)
{
int fd;
fd = open(REGION_PM_TMP_PATH, O_RDWR, 0644);
if (fd < 0) {
perror(REGION_PM_TMP_PATH);
exit(-1);
}
return mmap(REGION_PM_PTR, REGION_PM_SIZE, PROT, MAP_SHARED|MAP_SYNC,
fd, 0);
}
int main(int argc, char **argv)
{
char *regm, *regp, *remap;
int ret;
regm = mmap(REGION_MEM_PTR, REGION_MEM_SIZE, PROT, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0);
if (regm == MAP_FAILED) {
perror("regm");
return -1;
}
regp = map_tmp_pm_region();
if (regp == MAP_FAILED) {
perror("regp");
return -1;
}
memset(regm, 'a', REGION_MEM_SIZE);
memset(regp, 'i', REGION_PM_SIZE);
remap = mremap(regp + REMAP_PM_OFF, REMAP_SIZE, REMAP_SIZE,
MREMAP_MAYMOVE|MREMAP_FIXED, regm + REMAP_MEM_OFF);
if (remap != regm + REMAP_MEM_OFF) {
perror("mremap");
return -1;
}
*(regm + REMAP_MEM_OFF) = 0x00;
return 0;
}
4. Then I was able to see the "Corrupted page table" message in dmesg.
Best regards,
Fan
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] mm: Fix mremap not considering huge pmd devmap
2020-06-05 5:09 ` Fan Yang
@ 2020-06-05 19:14 ` Ajay Kaher
0 siblings, 0 replies; 4+ messages in thread
From: Ajay Kaher @ 2020-06-05 19:14 UTC (permalink / raw)
To: fan_yang
Cc: dan.j.williams, kirill.shutemov, linux-kernel, torvalds, gregkh,
srivatsab, srivatsa, akaher
Thanks Fan, this scenario works to reproduce on v4.9.
And following fix works for v4.9:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/commit/?h=linux-4.9.y&id=44cb51d5b4a736446b728bbde8407844d71843ef
-Ajay
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-06-05 19:15 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-04 10:22 [PATCH v3] mm: Fix mremap not considering huge pmd devmap Fan Yang
2020-06-04 18:23 ` Ajay Kaher
2020-06-05 5:09 ` Fan Yang
2020-06-05 19:14 ` Ajay Kaher
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).