diff mbox series

[2/2] mm: Abstract moving to the next PFN

Message ID 20230920035336.854212-2-willy@infradead.org (mailing list archive)
State New
Headers show
Series [1/2] mm: Report success more often from filemap_map_folio_range() | expand

Commit Message

Matthew Wilcox Sept. 20, 2023, 3:53 a.m. UTC
In order to fix the L1TF vulnerability, x86 can invert the PTE bits for
PROT_NONE VMAs, which means we cannot move from one PTE to the next by
adding 1 to the PFN field of the PTE.  Abstract advancing the PTE to
the next PFN through a pte_next_pfn() function/macro.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Fixes: bcc6cc832573 ("mm: add default definition of set_ptes()")
Reported-by: syzbot+55cc72f8cc3a549119df@syzkaller.appspotmail.com
---
 arch/x86/include/asm/pgtable.h | 8 ++++++++
 include/linux/pgtable.h        | 6 +++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

Comments

Matthew Wilcox Sept. 20, 2023, 4:07 a.m. UTC | #1
On Wed, Sep 20, 2023 at 04:53:36AM +0100, Matthew Wilcox (Oracle) wrote:
> In order to fix the L1TF vulnerability, x86 can invert the PTE bits for
> PROT_NONE VMAs, which means we cannot move from one PTE to the next by
> adding 1 to the PFN field of the PTE.  Abstract advancing the PTE to
> the next PFN through a pte_next_pfn() function/macro.

Argh, wrong version.  New version coming up.
kernel test robot Sept. 20, 2023, 9:19 a.m. UTC | #2
Hi Matthew,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]

url:    https://github.com/intel-lab-lkp/linux/commits/Matthew-Wilcox-Oracle/mm-Abstract-moving-to-the-next-PFN/20230920-115500
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20230920035336.854212-2-willy%40infradead.org
patch subject: [PATCH 2/2] mm: Abstract moving to the next PFN
config: um-i386_defconfig (https://download.01.org/0day-ci/archive/20230920/202309201731.Tr9SZYEz-lkp@intel.com/config)
compiler: gcc-7 (Ubuntu 7.5.0-6ubuntu2) 7.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230920/202309201731.Tr9SZYEz-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309201731.Tr9SZYEz-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/mm.h:29:0,
                    from include/linux/ring_buffer.h:5,
                    from include/linux/trace_events.h:6,
                    from include/trace/syscall.h:7,
                    from include/linux/syscalls.h:90,
                    from init/main.c:21:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from arch/x86/um/ptrace_32.c:6:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/x86/um/ptrace_32.c: At top level:
   arch/x86/um/ptrace_32.c:15:6: warning: no previous declaration for 'arch_switch_to' [-Wmissing-declarations]
    void arch_switch_to(struct task_struct *to)
         ^~~~~~~~~~~~~~
   arch/x86/um/ptrace_32.c:28:5: warning: no previous declaration for 'is_syscall' [-Wmissing-declarations]
    int is_syscall(unsigned long addr)
        ^~~~~~~~~~
   arch/x86/um/ptrace_32.c:125:5: warning: no previous declaration for 'poke_user' [-Wmissing-declarations]
    int poke_user(struct task_struct *child, long addr, long data)
        ^~~~~~~~~
   arch/x86/um/ptrace_32.c:177:5: warning: no previous declaration for 'peek_user' [-Wmissing-declarations]
    int peek_user(struct task_struct *child, long addr, long data)
        ^~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from include/linux/pid_namespace.h:7,
                    from include/linux/ptrace.h:10,
                    from arch/x86/um/signal.c:9:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/x86/um/signal.c: At top level:
   arch/x86/um/signal.c:453:6: warning: no previous declaration for 'sys_sigreturn' [-Wmissing-declarations]
    long sys_sigreturn(void)
         ^~~~~~~~~~~~~
   arch/x86/um/signal.c:560:6: warning: no previous declaration for 'sys_rt_sigreturn' [-Wmissing-declarations]
    long sys_rt_sigreturn(void)
         ^~~~~~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from include/linux/ring_buffer.h:5,
                    from include/linux/trace_events.h:6,
                    from include/trace/syscall.h:7,
                    from include/linux/syscalls.h:90,
                    from arch/x86/um/tls_32.c:8:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/x86/um/tls_32.c: At top level:
   arch/x86/um/tls_32.c:23:5: warning: no previous declaration for 'do_set_thread_area' [-Wmissing-declarations]
    int do_set_thread_area(struct user_desc *info)
        ^~~~~~~~~~~~~~~~~~
   arch/x86/um/tls_32.c:39:5: warning: no previous declaration for 'do_get_thread_area' [-Wmissing-declarations]
    int do_get_thread_area(struct user_desc *info)
        ^~~~~~~~~~~~~~~~~~
   arch/x86/um/tls_32.c:184:5: warning: no previous declaration for 'arch_switch_tls' [-Wmissing-declarations]
    int arch_switch_tls(struct task_struct *to)
        ^~~~~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from include/linux/coredump.h:6,
                    from arch/x86/um/elfcore.c:3:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/x86/um/elfcore.c: At top level:
   arch/x86/um/elfcore.c:10:12: warning: no previous declaration for 'elf_core_extra_phdrs' [-Wmissing-declarations]
    Elf32_Half elf_core_extra_phdrs(struct coredump_params *cprm)
               ^~~~~~~~~~~~~~~~~~~~
   arch/x86/um/elfcore.c:15:5: warning: no previous declaration for 'elf_core_write_extra_phdrs' [-Wmissing-declarations]
    int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
        ^~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/um/elfcore.c:42:5: warning: no previous declaration for 'elf_core_write_extra_data' [-Wmissing-declarations]
    int elf_core_write_extra_data(struct coredump_params *cprm)
        ^~~~~~~~~~~~~~~~~~~~~~~~~
   arch/x86/um/elfcore.c:63:8: warning: no previous declaration for 'elf_core_extra_data_size' [-Wmissing-declarations]
    size_t elf_core_extra_data_size(struct coredump_params *cprm)
           ^~~~~~~~~~~~~~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from include/linux/kallsyms.h:13,
                    from include/linux/ftrace.h:13,
                    from include/linux/kprobes.h:28,
                    from include/linux/kgdb.h:19,
                    from kernel/panic.c:15:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   kernel/panic.c: In function '__warn':
   kernel/panic.c:670:3: warning: function '__warn' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
      vprintk(args->fmt, args->args);
      ^~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from include/linux/memblock.h:12,
                    from arch/um/kernel/mem.c:8:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/um/kernel/mem.c: At top level:
   arch/um/kernel/mem.c:202:8: warning: no previous declaration for 'pgd_alloc' [-Wmissing-declarations]
    pgd_t *pgd_alloc(struct mm_struct *mm)
           ^~~~~~~~~
   arch/um/kernel/mem.c:215:7: warning: no previous declaration for 'uml_kmalloc' [-Wmissing-declarations]
    void *uml_kmalloc(int size, int flags)
          ^~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from arch/um/kernel/process.c:12:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/um/kernel/process.c: At top level:
   arch/um/kernel/process.c:51:5: warning: no previous declaration for 'pid_to_processor_id' [-Wmissing-declarations]
    int pid_to_processor_id(int pid)
        ^~~~~~~~~~~~~~~~~~~
   arch/um/kernel/process.c:87:7: warning: no previous declaration for '__switch_to' [-Wmissing-declarations]
    void *__switch_to(struct task_struct *from, struct task_struct *to)
          ^~~~~~~~~~~
   arch/um/kernel/process.c: In function 'new_thread_handler':
   arch/um/kernel/process.c:122:21: warning: variable 'n' set but not used [-Wunused-but-set-variable]
     int (*fn)(void *), n;
                        ^
   arch/um/kernel/process.c: At top level:
   arch/um/kernel/process.c:140:6: warning: no previous declaration for 'fork_handler' [-Wmissing-declarations]
    void fork_handler(void)
         ^~~~~~~~~~~~
   arch/um/kernel/process.c:217:6: warning: no previous declaration for 'arch_cpu_idle' [-Wmissing-declarations]
    void arch_cpu_idle(void)
         ^~~~~~~~~~~~~
   arch/um/kernel/process.c:253:5: warning: no previous declaration for 'copy_to_user_proc' [-Wmissing-declarations]
    int copy_to_user_proc(void __user *to, void *from, int size)
        ^~~~~~~~~~~~~~~~~
   arch/um/kernel/process.c:263:5: warning: no previous declaration for 'clear_user_proc' [-Wmissing-declarations]
    int clear_user_proc(void __user *buf, int size)
        ^~~~~~~~~~~~~~~
   arch/um/kernel/process.c:316:12: warning: no previous declaration for 'make_proc_sysemu' [-Wmissing-declarations]
    int __init make_proc_sysemu(void)
               ^~~~~~~~~~~~~~~~
   arch/um/kernel/process.c:356:15: warning: no previous declaration for 'arch_align_stack' [-Wmissing-declarations]
    unsigned long arch_align_stack(unsigned long sp)
                  ^~~~~~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from include/linux/oom.h:11,
                    from arch/um/kernel/reboot.c:11:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/um/kernel/reboot.c: At top level:
   arch/um/kernel/reboot.c:45:6: warning: no previous declaration for 'machine_restart' [-Wmissing-declarations]
    void machine_restart(char * __unused)
         ^~~~~~~~~~~~~~~
   arch/um/kernel/reboot.c:51:6: warning: no previous declaration for 'machine_power_off' [-Wmissing-declarations]
    void machine_power_off(void)
         ^~~~~~~~~~~~~~~~~
   arch/um/kernel/reboot.c:57:6: warning: no previous declaration for 'machine_halt' [-Wmissing-declarations]
    void machine_halt(void)
         ^~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from arch/um/kernel/tlb.c:6:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/um/kernel/tlb.c: At top level:
   arch/um/kernel/tlb.c:579:6: warning: no previous declaration for 'flush_tlb_mm_range' [-Wmissing-declarations]
    void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
         ^~~~~~~~~~~~~~~~~~
   arch/um/kernel/tlb.c:594:6: warning: no previous declaration for 'force_flush_all' [-Wmissing-declarations]
    void force_flush_all(void)
         ^~~~~~~~~~~~~~~
--
   In file included from include/linux/mm.h:29:0,
                    from arch/um/kernel/um_arch.c:9:
   include/linux/pgtable.h: In function 'set_ptes':
>> include/linux/pgtable.h:209:34: error: invalid operands to binary + (have 'pte_t {aka struct <anonymous>}' and 'long unsigned int')
    #define pte_next_pfn(pte) ((pte) + (1UL << PFN_PTE_SHIFT))
                                     ^
   include/linux/pgtable.h:238:9: note: in expansion of macro 'pte_next_pfn'
      pte = pte_next_pfn(pte);
            ^~~~~~~~~~~~
   arch/um/kernel/um_arch.c: At top level:
   arch/um/kernel/um_arch.c:408:19: warning: no previous declaration for 'read_initrd' [-Wmissing-declarations]
    int __init __weak read_initrd(void)
                      ^~~~~~~~~~~
   arch/um/kernel/um_arch.c:461:7: warning: no previous declaration for 'text_poke' [-Wmissing-declarations]
    void *text_poke(void *addr, const void *opcode, size_t len)
          ^~~~~~~~~
   arch/um/kernel/um_arch.c:473:6: warning: no previous declaration for 'text_poke_sync' [-Wmissing-declarations]
    void text_poke_sync(void)
         ^~~~~~~~~~~~~~
..


vim +209 include/linux/pgtable.h

   207	
   208	#ifndef pte_next_pfn
 > 209	#define pte_next_pfn(pte)	((pte) + (1UL << PFN_PTE_SHIFT))
   210	#endif
   211
diff mbox series

Patch

diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index d6ad98ca1288..e02b179ec659 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -955,6 +955,14 @@  static inline int pte_same(pte_t a, pte_t b)
 	return a.pte == b.pte;
 }
 
+static inline pte_t pte_next_pfn(pte_t pte)
+{
+	if (__pte_needs_invert(pte_val(pte)))
+		return __pte(pte_val(pte) - (1UL << PFN_PTE_SHIFT));
+	return __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT));
+}
+#define pte_next_pfn	pte_next_pfn
+
 static inline int pte_present(pte_t a)
 {
 	return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 1fba072b3dac..5bdf78aa7852 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -205,6 +205,10 @@  static inline int pmd_young(pmd_t pmd)
 #define arch_flush_lazy_mmu_mode()	do {} while (0)
 #endif
 
+#ifndef pte_next_pfn
+#define pte_next_pfn(pte)	((pte) + (1UL << PFN_PTE_SHIFT))
+#endif
+
 #ifndef set_ptes
 /**
  * set_ptes - Map consecutive pages to a contiguous range of addresses.
@@ -231,7 +235,7 @@  static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
 		if (--nr == 0)
 			break;
 		ptep++;
-		pte = __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT));
+		pte = pte_next_pfn(pte);
 	}
 	arch_leave_lazy_mmu_mode();
 }