Pull x86 mm updates from Ingo Molnar: "The changes in here are: - text_poke() fixes and an extensive set of executability lockdowns, to (hopefully) eliminate the last residual circumstances under which we are using W|X mappings even temporarily on x86 kernels. This required a broad range of surgery in text patching facilities, module loading, trampoline handling and other bits. - tweak page fault messages to be more informative and more structured. - remove DISCONTIGMEM support on x86-32 and make SPARSEMEM the default. - reduce KASLR granularity on 5-level paging kernels from 512 GB to 1 GB. - misc other changes and updates" * 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits) x86/mm: Initialize PGD cache during mm initialization x86/alternatives: Add comment about module removal races x86/kprobes: Use vmalloc special flag x86/ftrace: Use vmalloc special flag bpf: Use vmalloc special flag modules: Use vmalloc special flag mm/vmalloc: Add flag for freeing of special permsissions mm/hibernation: Make hibernation handle unmapped pages x86/mm/cpa: Add set_direct_map_*() functions x86/alternatives: Remove the return value of text_poke_*() x86/jump-label: Remove support for custom text poker x86/modules: Avoid breaking W^X while loading modules x86/kprobes: Set instruction page as executable x86/ftrace: Set trampoline pages as executable x86/kgdb: Avoid redundant comparison of patched code x86/alternatives: Use temporary mm for text poking x86/alternatives: Initialize temporary mm for patching fork: Provide a function for copying init_mm uprobes: Initialize uprobes earlier x86/mm: Save debug registers when loading a temporary mm ...
Showing the changes to include/linux (6 of 40 files). Show all
Unified · Split
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/set_memory.h> |
| 21 | 21 | #include <linux/kallsyms.h> |
| 22 | 22 | #include <linux/if_vlan.h> |
| 23 | +#include <linux/vmalloc.h> | |
| 23 | 24 | |
| 24 | 25 | #include <net/sch_generic.h> |
| 25 | 26 | |
| @@ -503,7 +504,6 @@ struct bpf_prog { · 477 unmodified lines | ||
| 503 | 504 | u16 pages; /* Number of allocated pages */ |
| 504 | 505 | u16 jited:1, /* Is our filter JIT'ed? */ |
| 505 | 506 | jit_requested:1,/* archs need to JIT the prog */ |
| 506 | − undo_set_mem:1, /* Passed set_memory_ro() checkpoint */ | |
| 507 | 507 | gpl_compatible:1, /* Is filter GPL compatible? */ |
| 508 | 508 | cb_access:1, /* Is control block accessed? */ |
| 509 | 509 | dst_needed:1, /* Do we need dst entry? */ |
| @@ -733,24 +733,15 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default) · 223 unmodified lines | ||
| 733 | 733 | |
| 734 | 734 | static inline void bpf_prog_lock_ro(struct bpf_prog *fp) |
| 735 | 735 | { |
| 736 | − fp->undo_set_mem = 1; | |
| 736 | + set_vm_flush_reset_perms(fp); | |
| 737 | 737 | set_memory_ro((unsigned long)fp, fp->pages); |
| 738 | 738 | } |
| 739 | 739 | |
| 740 | −static inline void bpf_prog_unlock_ro(struct bpf_prog *fp) | |
| 741 | −{ | |
| 742 | − if (fp->undo_set_mem) | |
| 743 | − set_memory_rw((unsigned long)fp, fp->pages); | |
| 744 | −} | |
| 745 | − | |
| 746 | 740 | static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr) |
| 747 | 741 | { |
| 742 | + set_vm_flush_reset_perms(hdr); | |
| 748 | 743 | set_memory_ro((unsigned long)hdr, hdr->pages); |
| 749 | −} | |
| 750 | − | |
| 751 | −static inline void bpf_jit_binary_unlock_ro(struct bpf_binary_header *hdr) | |
| 752 | −{ | |
| 753 | − set_memory_rw((unsigned long)hdr, hdr->pages); | |
| 744 | + set_memory_x((unsigned long)hdr, hdr->pages); | |
| 754 | 745 | } |
| 755 | 746 | |
| 756 | 747 | static inline struct bpf_binary_header * |
| @@ -788,7 +779,6 @@ void __bpf_prog_free(struct bpf_prog *fp); · 31 unmodified lines | ||
| 788 | 779 | |
| 789 | 780 | static inline void bpf_prog_unlock_free(struct bpf_prog *fp) |
| 790 | 781 | { |
| 791 | − bpf_prog_unlock_ro(fp); | |
| 792 | 782 | __bpf_prog_free(fp); |
| 793 | 783 | } |
| 794 | 784 | |
| @@ -2610,37 +2610,31 @@ static inline void kernel_poison_pages(struct page *page, int numpages, · 2609 unmodified lines | ||
| 2610 | 2610 | int enable) { } |
| 2611 | 2611 | #endif |
| 2612 | 2612 | |
| 2613 | −#ifdef CONFIG_DEBUG_PAGEALLOC | |
| 2614 | 2613 | extern bool _debug_pagealloc_enabled; |
| 2615 | −extern void __kernel_map_pages(struct page *page, int numpages, int enable); | |
| 2616 | 2614 | |
| 2617 | 2615 | static inline bool debug_pagealloc_enabled(void) |
| 2618 | 2616 | { |
| 2619 | − return _debug_pagealloc_enabled; | |
| 2617 | + return IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) && _debug_pagealloc_enabled; | |
| 2620 | 2618 | } |
| 2621 | 2619 | |
| 2620 | +#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP) | |
| 2621 | +extern void __kernel_map_pages(struct page *page, int numpages, int enable); | |
| 2622 | + | |
| 2622 | 2623 | static inline void |
| 2623 | 2624 | kernel_map_pages(struct page *page, int numpages, int enable) |
| 2624 | 2625 | { |
| 2625 | − if (!debug_pagealloc_enabled()) | |
| 2626 | − return; | |
| 2627 | − | |
| 2628 | 2626 | __kernel_map_pages(page, numpages, enable); |
| 2629 | 2627 | } |
| 2630 | 2628 | #ifdef CONFIG_HIBERNATION |
| 2631 | 2629 | extern bool kernel_page_present(struct page *page); |
| 2632 | 2630 | #endif /* CONFIG_HIBERNATION */ |
| 2633 | −#else /* CONFIG_DEBUG_PAGEALLOC */ | |
| 2631 | +#else /* CONFIG_DEBUG_PAGEALLOC || CONFIG_ARCH_HAS_SET_DIRECT_MAP */ | |
| 2634 | 2632 | static inline void |
| 2635 | 2633 | kernel_map_pages(struct page *page, int numpages, int enable) {} |
| 2636 | 2634 | #ifdef CONFIG_HIBERNATION |
| 2637 | 2635 | static inline bool kernel_page_present(struct page *page) { return true; } |
| 2638 | 2636 | #endif /* CONFIG_HIBERNATION */ |
| 2639 | −static inline bool debug_pagealloc_enabled(void) | |
| 2640 | −{ | |
| 2641 | − return false; | |
| 2642 | −} | |
| 2643 | −#endif /* CONFIG_DEBUG_PAGEALLOC */ | |
| 2637 | +#endif /* CONFIG_DEBUG_PAGEALLOC || CONFIG_ARCH_HAS_SET_DIRECT_MAP */ | |
| 2644 | 2638 | |
| 2645 | 2639 | #ifdef __HAVE_ARCH_GATE_AREA |
| 2646 | 2640 | extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm); |
| @@ -76,6 +76,7 @@ extern void exit_itimers(struct signal_struct *); · 75 unmodified lines | ||
| 76 | 76 | extern long _do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *, unsigned long); |
| 77 | 77 | extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); |
| 78 | 78 | struct task_struct *fork_idle(int); |
| 79 | +struct mm_struct *copy_init_mm(void); | |
| 79 | 80 | extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
| 80 | 81 | extern long kernel_wait4(pid_t, int __user *, int, struct rusage *); |
| 81 | 82 | |
| @@ -17,6 +17,17 @@ static inline int set_memory_x(unsigned long addr, int numpages) { return 0; } · 16 unmodified lines | ||
| 17 | 17 | static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; } |
| 18 | 18 | #endif |
| 19 | 19 | |
| 20 | +#ifndef CONFIG_ARCH_HAS_SET_DIRECT_MAP | |
| 21 | +static inline int set_direct_map_invalid_noflush(struct page *page) | |
| 22 | +{ | |
| 23 | + return 0; | |
| 24 | +} | |
| 25 | +static inline int set_direct_map_default_noflush(struct page *page) | |
| 26 | +{ | |
| 27 | + return 0; | |
| 28 | +} | |
| 29 | +#endif | |
| 30 | + | |
| 20 | 31 | #ifndef set_mce_nospec |
| 21 | 32 | static inline int set_mce_nospec(unsigned long pfn) |
| 22 | 33 | { |
| @@ -115,6 +115,7 @@ struct uprobes_state { · 114 unmodified lines | ||
| 115 | 115 | struct xol_area *xol_area; |
| 116 | 116 | }; |
| 117 | 117 | |
| 118 | +extern void __init uprobes_init(void); | |
| 118 | 119 | extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); |
| 119 | 120 | extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); |
| 120 | 121 | extern bool is_swbp_insn(uprobe_opcode_t *insn); |
| @@ -154,6 +155,10 @@ extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, · 33 unmodified lines | ||
| 154 | 155 | struct uprobes_state { |
| 155 | 156 | }; |
| 156 | 157 | |
| 158 | +static inline void uprobes_init(void) | |
| 159 | +{ | |
| 160 | +} | |
| 161 | + | |
| 157 | 162 | #define uprobe_get_trap_addr(regs) instruction_pointer(regs) |
| 158 | 163 | |
| 159 | 164 | static inline int |
| @@ -21,6 +21,11 @@ struct notifier_block; /* in notifier.h */ · 20 unmodified lines | ||
| 21 | 21 | #define VM_UNINITIALIZED 0x00000020 /* vm_struct is not fully initialized */ |
| 22 | 22 | #define VM_NO_GUARD 0x00000040 /* don't add guard page */ |
| 23 | 23 | #define VM_KASAN 0x00000080 /* has allocated kasan shadow memory */ |
| 24 | +/* | |
| 25 | + * Memory with VM_FLUSH_RESET_PERMS cannot be freed in an interrupt or with | |
| 26 | + * vfree_atomic(). | |
| 27 | + */ | |
| 28 | +#define VM_FLUSH_RESET_PERMS 0x00000100 /* Reset direct map and flush TLB on unmap */ | |
| 24 | 29 | /* bits [20..32] reserved for arch specific ioremap internals */ |
| 25 | 30 | |
| 26 | 31 | /* |
| @@ -142,6 +147,13 @@ extern int map_kernel_range_noflush(unsigned long start, unsigned long size, · 115 unmodified lines | ||
| 142 | 147 | pgprot_t prot, struct page **pages); |
| 143 | 148 | extern void unmap_kernel_range_noflush(unsigned long addr, unsigned long size); |
| 144 | 149 | extern void unmap_kernel_range(unsigned long addr, unsigned long size); |
| 150 | +static inline void set_vm_flush_reset_perms(void *addr) | |
| 151 | +{ | |
| 152 | + struct vm_struct *vm = find_vm_area(addr); | |
| 153 | + | |
| 154 | + if (vm) | |
| 155 | + vm->flags |= VM_FLUSH_RESET_PERMS; | |
| 156 | +} | |
| 145 | 157 | #else |
| 146 | 158 | static inline int |
| 147 | 159 | map_kernel_range_noflush(unsigned long start, unsigned long size, |
| @@ -157,6 +169,9 @@ static inline void · 9 unmodified lines | ||
| 157 | 169 | unmap_kernel_range(unsigned long addr, unsigned long size) |
| 158 | 170 | { |
| 159 | 171 | } |
| 172 | +static inline void set_vm_flush_reset_perms(void *addr) | |
| 173 | +{ | |
| 174 | +} | |
| 160 | 175 | #endif |
| 161 | 176 | |
| 162 | 177 | /* Allocate/destroy a 'vmalloc' VM area. */ |