Loading arch/x86/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ config X86 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_REFCOUNT select ARCH_HAS_REFCOUNT select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 select ARCH_HAS_UACCESS_MCSAFE if X86_64 select ARCH_HAS_SET_MEMORY select ARCH_HAS_SET_MEMORY select ARCH_HAS_SG_CHAIN select ARCH_HAS_SG_CHAIN select ARCH_HAS_STRICT_KERNEL_RWX select ARCH_HAS_STRICT_KERNEL_RWX Loading arch/x86/Kconfig.debug +3 −0 Original line number Original line Diff line number Diff line Loading @@ -72,6 +72,9 @@ config EARLY_PRINTK_USB_XDBC You should normally say N here, unless you want to debug early You should normally say N here, unless you want to debug early crashes or need a very simple printk logging facility. crashes or need a very simple printk logging facility. config MCSAFE_TEST def_bool n config X86_PTDUMP_CORE config X86_PTDUMP_CORE def_bool n def_bool n Loading arch/x86/include/asm/mcsafe_test.h 0 → 100644 +75 −0 Original line number Original line Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _MCSAFE_TEST_H_ #define _MCSAFE_TEST_H_ #ifndef __ASSEMBLY__ #ifdef CONFIG_MCSAFE_TEST extern unsigned long mcsafe_test_src; extern unsigned long mcsafe_test_dst; static inline void mcsafe_inject_src(void *addr) { if (addr) mcsafe_test_src = (unsigned long) addr; else mcsafe_test_src = ~0UL; } static inline void mcsafe_inject_dst(void *addr) { if (addr) mcsafe_test_dst = (unsigned long) addr; else mcsafe_test_dst = ~0UL; } #else /* CONFIG_MCSAFE_TEST */ static inline void mcsafe_inject_src(void *addr) { } static inline void mcsafe_inject_dst(void *addr) { } #endif /* CONFIG_MCSAFE_TEST */ #else /* __ASSEMBLY__ */ #include <asm/export.h> #ifdef CONFIG_MCSAFE_TEST .macro MCSAFE_TEST_CTL .pushsection .data .align 8 .globl mcsafe_test_src mcsafe_test_src: .quad 0 EXPORT_SYMBOL_GPL(mcsafe_test_src) .globl mcsafe_test_dst mcsafe_test_dst: .quad 0 EXPORT_SYMBOL_GPL(mcsafe_test_dst) .popsection .endm .macro MCSAFE_TEST_SRC reg count target leaq \count(\reg), %r9 cmp mcsafe_test_src, %r9 ja \target .endm .macro MCSAFE_TEST_DST reg count target leaq \count(\reg), %r9 cmp mcsafe_test_dst, %r9 ja \target .endm #else .macro MCSAFE_TEST_CTL .endm .macro MCSAFE_TEST_SRC reg count target .endm .macro MCSAFE_TEST_DST reg count target .endm #endif /* CONFIG_MCSAFE_TEST */ #endif /* __ASSEMBLY__ */ #endif /* _MCSAFE_TEST_H_ */ arch/x86/include/asm/string_64.h +6 −4 Original line number Original line Diff line number Diff line Loading @@ -116,7 +116,8 @@ int strcmp(const char *cs, const char *ct); #endif #endif #define __HAVE_ARCH_MEMCPY_MCSAFE 1 #define __HAVE_ARCH_MEMCPY_MCSAFE 1 __must_check int memcpy_mcsafe_unrolled(void *dst, const void *src, size_t cnt); __must_check unsigned long __memcpy_mcsafe(void *dst, const void *src, size_t cnt); DECLARE_STATIC_KEY_FALSE(mcsafe_key); DECLARE_STATIC_KEY_FALSE(mcsafe_key); /** /** Loading @@ -131,14 +132,15 @@ DECLARE_STATIC_KEY_FALSE(mcsafe_key); * actually do machine check recovery. Everyone else can just * actually do machine check recovery. Everyone else can just * use memcpy(). * use memcpy(). * * * Return 0 for success, -EFAULT for fail * Return 0 for success, or number of bytes not copied if there was an * exception. */ */ static __always_inline __must_check int static __always_inline __must_check unsigned long memcpy_mcsafe(void *dst, const void *src, size_t cnt) memcpy_mcsafe(void *dst, const void *src, size_t cnt) { { #ifdef CONFIG_X86_MCE #ifdef CONFIG_X86_MCE if (static_branch_unlikely(&mcsafe_key)) if (static_branch_unlikely(&mcsafe_key)) return memcpy_mcsafe_unrolled(dst, src, cnt); return __memcpy_mcsafe(dst, src, cnt); else else #endif #endif memcpy(dst, src, cnt); memcpy(dst, src, cnt); Loading arch/x86/include/asm/uaccess_64.h +14 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,17 @@ copy_user_generic(void *to, const void *from, unsigned len) return ret; return ret; } } static __always_inline __must_check unsigned long copy_to_user_mcsafe(void *to, const void *from, unsigned len) { unsigned long ret; __uaccess_begin(); ret = memcpy_mcsafe(to, from, len); __uaccess_end(); return ret; } static __always_inline __must_check unsigned long static __always_inline __must_check unsigned long raw_copy_from_user(void *dst, const void __user *src, unsigned long size) raw_copy_from_user(void *dst, const void __user *src, unsigned long size) { { Loading Loading @@ -194,4 +205,7 @@ __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size) unsigned long unsigned long copy_user_handle_tail(char *to, char *from, unsigned len); copy_user_handle_tail(char *to, char *from, unsigned len); unsigned long mcsafe_handle_tail(char *to, char *from, unsigned len); #endif /* _ASM_X86_UACCESS_64_H */ #endif /* _ASM_X86_UACCESS_64_H */ Loading
arch/x86/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -60,6 +60,7 @@ config X86 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_REFCOUNT select ARCH_HAS_REFCOUNT select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 select ARCH_HAS_UACCESS_MCSAFE if X86_64 select ARCH_HAS_SET_MEMORY select ARCH_HAS_SET_MEMORY select ARCH_HAS_SG_CHAIN select ARCH_HAS_SG_CHAIN select ARCH_HAS_STRICT_KERNEL_RWX select ARCH_HAS_STRICT_KERNEL_RWX Loading
arch/x86/Kconfig.debug +3 −0 Original line number Original line Diff line number Diff line Loading @@ -72,6 +72,9 @@ config EARLY_PRINTK_USB_XDBC You should normally say N here, unless you want to debug early You should normally say N here, unless you want to debug early crashes or need a very simple printk logging facility. crashes or need a very simple printk logging facility. config MCSAFE_TEST def_bool n config X86_PTDUMP_CORE config X86_PTDUMP_CORE def_bool n def_bool n Loading
arch/x86/include/asm/mcsafe_test.h 0 → 100644 +75 −0 Original line number Original line Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _MCSAFE_TEST_H_ #define _MCSAFE_TEST_H_ #ifndef __ASSEMBLY__ #ifdef CONFIG_MCSAFE_TEST extern unsigned long mcsafe_test_src; extern unsigned long mcsafe_test_dst; static inline void mcsafe_inject_src(void *addr) { if (addr) mcsafe_test_src = (unsigned long) addr; else mcsafe_test_src = ~0UL; } static inline void mcsafe_inject_dst(void *addr) { if (addr) mcsafe_test_dst = (unsigned long) addr; else mcsafe_test_dst = ~0UL; } #else /* CONFIG_MCSAFE_TEST */ static inline void mcsafe_inject_src(void *addr) { } static inline void mcsafe_inject_dst(void *addr) { } #endif /* CONFIG_MCSAFE_TEST */ #else /* __ASSEMBLY__ */ #include <asm/export.h> #ifdef CONFIG_MCSAFE_TEST .macro MCSAFE_TEST_CTL .pushsection .data .align 8 .globl mcsafe_test_src mcsafe_test_src: .quad 0 EXPORT_SYMBOL_GPL(mcsafe_test_src) .globl mcsafe_test_dst mcsafe_test_dst: .quad 0 EXPORT_SYMBOL_GPL(mcsafe_test_dst) .popsection .endm .macro MCSAFE_TEST_SRC reg count target leaq \count(\reg), %r9 cmp mcsafe_test_src, %r9 ja \target .endm .macro MCSAFE_TEST_DST reg count target leaq \count(\reg), %r9 cmp mcsafe_test_dst, %r9 ja \target .endm #else .macro MCSAFE_TEST_CTL .endm .macro MCSAFE_TEST_SRC reg count target .endm .macro MCSAFE_TEST_DST reg count target .endm #endif /* CONFIG_MCSAFE_TEST */ #endif /* __ASSEMBLY__ */ #endif /* _MCSAFE_TEST_H_ */
arch/x86/include/asm/string_64.h +6 −4 Original line number Original line Diff line number Diff line Loading @@ -116,7 +116,8 @@ int strcmp(const char *cs, const char *ct); #endif #endif #define __HAVE_ARCH_MEMCPY_MCSAFE 1 #define __HAVE_ARCH_MEMCPY_MCSAFE 1 __must_check int memcpy_mcsafe_unrolled(void *dst, const void *src, size_t cnt); __must_check unsigned long __memcpy_mcsafe(void *dst, const void *src, size_t cnt); DECLARE_STATIC_KEY_FALSE(mcsafe_key); DECLARE_STATIC_KEY_FALSE(mcsafe_key); /** /** Loading @@ -131,14 +132,15 @@ DECLARE_STATIC_KEY_FALSE(mcsafe_key); * actually do machine check recovery. Everyone else can just * actually do machine check recovery. Everyone else can just * use memcpy(). * use memcpy(). * * * Return 0 for success, -EFAULT for fail * Return 0 for success, or number of bytes not copied if there was an * exception. */ */ static __always_inline __must_check int static __always_inline __must_check unsigned long memcpy_mcsafe(void *dst, const void *src, size_t cnt) memcpy_mcsafe(void *dst, const void *src, size_t cnt) { { #ifdef CONFIG_X86_MCE #ifdef CONFIG_X86_MCE if (static_branch_unlikely(&mcsafe_key)) if (static_branch_unlikely(&mcsafe_key)) return memcpy_mcsafe_unrolled(dst, src, cnt); return __memcpy_mcsafe(dst, src, cnt); else else #endif #endif memcpy(dst, src, cnt); memcpy(dst, src, cnt); Loading
arch/x86/include/asm/uaccess_64.h +14 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,17 @@ copy_user_generic(void *to, const void *from, unsigned len) return ret; return ret; } } static __always_inline __must_check unsigned long copy_to_user_mcsafe(void *to, const void *from, unsigned len) { unsigned long ret; __uaccess_begin(); ret = memcpy_mcsafe(to, from, len); __uaccess_end(); return ret; } static __always_inline __must_check unsigned long static __always_inline __must_check unsigned long raw_copy_from_user(void *dst, const void __user *src, unsigned long size) raw_copy_from_user(void *dst, const void __user *src, unsigned long size) { { Loading Loading @@ -194,4 +205,7 @@ __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size) unsigned long unsigned long copy_user_handle_tail(char *to, char *from, unsigned len); copy_user_handle_tail(char *to, char *from, unsigned len); unsigned long mcsafe_handle_tail(char *to, char *from, unsigned len); #endif /* _ASM_X86_UACCESS_64_H */ #endif /* _ASM_X86_UACCESS_64_H */