lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <23d21857-2672-b3cd-ee29-830076e62461@huawei.com> Date: Tue, 12 Dec 2017 11:13:03 +0800 From: chenjiankang <chenjiankang1@...wei.com> To: Catalin Marinas <catalin.marinas@....com> CC: Will Deacon <will.deacon@....com>, Yisheng Xie <xieyisheng1@...wei.com>, <qiuxishi@...wei.com>, <linux-kernel@...r.kernel.org>, <wangkefeng.wang@...wei.com> Subject: Re: a racy access flag clearing warning when calling mmap system call > On Fri, Dec 08, 2017 at 11:19:52AM +0800, chenjiankang wrote: >> 在 2017/12/7 21:23, Will Deacon 写道: >>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h >>> index 149d05fb9421..8fe103b1e101 100644 >>> --- a/arch/arm64/include/asm/pgtable.h >>> +++ b/arch/arm64/include/asm/pgtable.h >>> @@ -42,6 +42,8 @@ >>> #include <asm/cmpxchg.h> >>> #include <asm/fixmap.h> >>> #include <linux/mmdebug.h> >>> +#include <linux/mm_types.h> >>> +#include <linux/sched.h> >>> >>> extern void __pte_error(const char *file, int line, unsigned long val); >>> extern void __pmd_error(const char *file, int line, unsigned long val); >>> @@ -207,9 +209,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte) >>> } >>> } >>> >>> -struct mm_struct; >>> -struct vm_area_struct; >>> - >>> extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); >>> >>> /* >>> @@ -238,7 +237,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, >>> * hardware updates of the pte (ptep_set_access_flags safely changes >>> * valid ptes without going through an invalid entry). >>> */ >>> - if (pte_valid(*ptep) && pte_valid(pte)) { >>> + if (IS_ENABLED(CONFIG_DEBUG_VM) && pte_valid(*ptep) && pte_valid(pte) && >>> + (mm == current->active_mm || atomic_read(&mm->mm_users) > 1)) { >>> VM_WARN_ONCE(!pte_young(pte), >>> "%s: racy access flag clearing: 0x%016llx -> 0x%016llx", >>> __func__, pte_val(*ptep), pte_val(pte)); > [...] Hi Will: I contruct a simple use case that can reproduce this fail; like this: #define LEN 1024*1024*100 int main(void){ int* addr = NULL; int pid = -1; addr = (int*)mmap(NULL, LEN, PROT_READ | PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); madvise(addr, LEN, MADV_HUGEPAGE); memset(addr, 1, LEN); pid = fork(); if(pid==0){ printf("wow! I am a child!\n"); } else { printf("I am a father!\n"); mmap(addr, 1024*1024*10, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); } return 0; } And then, I use the will's modification,which can solve this problem; Will, this patch should send a upstream? >> From the print information, the only difference between pte and ptep is the PTE_SPECIAL bit. >> And the the PTE access bit is all zero. >> diff below. Whether the access bit of the new ptep should be judged to eliminate the >> false positive? > [...] >> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h >> index 2987d5a..3c1b0c6 100644 >> --- a/arch/arm64/include/asm/pgtable.h >> +++ b/arch/arm64/include/asm/pgtable.h >> @@ -206,7 +206,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, >> * valid ptes without going through an invalid entry). >> */ >> if (IS_ENABLED(CONFIG_ARM64_HW_AFDBM) && pte_valid(*ptep)) { >> - VM_WARN_ONCE(!pte_young(pte), >> + VM_WARN_ONCE(!pte_young(pte) && pte_young(*ptep), >> "%s: racy access flag clearing: %016llx -> %016llx", >> __func__, pte_val(*ptep), pte_val(pte)); > > It's actually the other way around: *ptep being "old" (AF = 0) could at > any point be made "young" by the hardware (AF = 1). This is racing with > the software update which keeps the AF bit 0. >
Powered by blists - more mailing lists