From c787a79b049ed4c51fe69843b5ac3a5c75edcc02 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 16 Oct 2019 15:03:50 -0400 Subject: mm: Add a mechanism to disable faults for a specific mapping This will be used to prevent a nasty cache coherency issue for O_DIRECT writes; O_DIRECT writes need to shoot down the range of the page cache corresponding to the part of the file being written to - but, if the file is mapped in, userspace can pass in an address in that mapping to pwrite(), causing those pages to be faulted back into the page cache in get_user_pages(). Signed-off-by: Kent Overstreet --- include/linux/sched.h | 1 + init/init_task.c | 1 + mm/memory.c | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 1db9042dede6..f3bbf171e97d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -679,6 +679,7 @@ struct task_struct { struct mm_struct *mm; struct mm_struct *active_mm; + struct address_space *faults_disabled_mapping; /* Per-thread vma caching: */ struct vmacache vmacache; diff --git a/init/init_task.c b/init/init_task.c index 92bbb6e9094f..6c0f1257234b 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -76,6 +76,7 @@ struct task_struct init_task .nr_cpus_allowed= NR_CPUS, .mm = NULL, .active_mm = &init_mm, + .faults_disabled_mapping = NULL, .restart_block = { .fn = do_no_restart_syscall, }, diff --git a/mm/memory.c b/mm/memory.c index ddf20bd0c317..c8d1e9419406 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3633,10 +3633,18 @@ static vm_fault_t do_fault(struct vm_fault *vmf) struct mm_struct *vm_mm = vma->vm_mm; vm_fault_t ret; - /* - * The VMA was not fully populated on mmap() or missing VM_DONTEXPAND - */ - if (!vma->vm_ops->fault) { + if (vma->vm_file && + vma->vm_file->f_mapping && + unlikely(vma->vm_file->f_mapping == + current->faults_disabled_mapping)) { + /* Faulting in pages for this mapping is currently disabled: */ + ret = VM_FAULT_SIGBUS; + } else if (!vma->vm_ops->fault) { + /* + * The VMA was not fully populated on mmap() or missing + * VM_DONTEXPAND + */ + /* * If we find a migration pmd entry or a none pmd entry, which * should never happen, return SIGBUS -- cgit v1.2.3