diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-10-16 15:03:50 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2020-05-06 17:14:17 -0400 |
commit | 52cf809aa1394d759dfe4eb88290aa4d99f00647 (patch) | |
tree | 95accb66e1b2bb3a86c99494684a2ead78ca7f62 | |
parent | a94d2540036e2a9b6da593e497efaa64b08c3f54 (diff) |
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 <kent.overstreet@gmail.com>
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | init/init_task.c | 1 | ||||
-rw-r--r-- | mm/gup.c | 6 |
3 files changed, 8 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index c69f308f3a53..96e4152cc9bc 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -687,6 +687,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 5aebe3be4d7c..2a275774eb52 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -75,6 +75,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, }, @@ -724,6 +724,12 @@ retry: if (unlikely(fatal_signal_pending(current))) return i ? i : -ERESTARTSYS; cond_resched(); + + if (current->faults_disabled_mapping && + vma->vm_file && + vma->vm_file->f_mapping == current->faults_disabled_mapping) + return -EFAULT; + page = follow_page_mask(vma, start, foll_flags, &page_mask); if (!page) { int ret; |