* [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).