4.4.245-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 4.4.245-rc1 review
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.245-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.4.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.4.245-rc1
David Edmondson <[email protected]>
KVM: x86: clflushopt should be treated as a no-op by emulation
Johannes Berg <[email protected]>
mac80211: always wind down STA state
Dmitry Torokhov <[email protected]>
Input: sunkbd - avoid use-after-free in teardown paths
Christophe Leroy <[email protected]>
powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
Dave Chinner <[email protected]>
xfs: validate cached inodes are free when allocated
Dave Chinner <[email protected]>
xfs: catch inode allocation state mismatch corruption
Krzysztof Kozlowski <[email protected]>
i2c: imx: Fix external abort on interrupt in exit paths
Nicholas Piggin <[email protected]>
powerpc/64s: flush L1D after user accesses
Nicholas Piggin <[email protected]>
powerpc/uaccess: Evaluate macro arguments once, before user access is allowed
Andrew Donnellan <[email protected]>
powerpc: Fix __clear_user() with KUAP enabled
Christophe Leroy <[email protected]>
powerpc: Implement user_access_begin and friends
Christophe Leroy <[email protected]>
powerpc: Add a framework for user access tracking
Nicholas Piggin <[email protected]>
powerpc/64s: flush L1D on kernel entry
Daniel Axtens <[email protected]>
powerpc/64s: move some exception handlers out of line
Daniel Axtens <[email protected]>
powerpc/64s: Define MASKABLE_RELON_EXCEPTION_PSERIES_OOL
-------------
Diffstat:
Documentation/kernel-parameters.txt | 7 + Makefile | 4 +- arch/powerpc/include/asm/book3s/64/kup-radix.h | 23 +++ arch/powerpc/include/asm/exception-64s.h | 15 +- arch/powerpc/include/asm/feature-fixups.h | 19 +++ arch/powerpc/include/asm/futex.h | 4 + arch/powerpc/include/asm/kup.h | 40 +++++ arch/powerpc/include/asm/security_features.h | 7 + arch/powerpc/include/asm/setup.h | 4 + arch/powerpc/include/asm/uaccess.h | 142 +++++++++++++---- arch/powerpc/kernel/exceptions-64s.S | 210 +++++++++++++++---------- arch/powerpc/kernel/head_8xx.S | 8 +- arch/powerpc/kernel/ppc_ksyms.c | 10 ++ arch/powerpc/kernel/setup_64.c | 138 ++++++++++++++++ arch/powerpc/kernel/vmlinux.lds.S | 14 ++ arch/powerpc/lib/checksum_wrappers_64.c | 4 + arch/powerpc/lib/feature-fixups.c | 104 ++++++++++++ arch/powerpc/lib/string.S | 2 +- arch/powerpc/lib/string_64.S | 4 +- arch/powerpc/platforms/powernv/setup.c | 15 ++ arch/powerpc/platforms/pseries/setup.c | 8 + arch/x86/kvm/emulate.c | 8 +- drivers/i2c/busses/i2c-imx.c | 25 +-- drivers/input/keyboard/sunkbd.c | 41 ++++- fs/xfs/xfs_icache.c | 58 ++++++- net/mac80211/sta_info.c | 18 +++ 26 files changed, 782 insertions(+), 150 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/15 powerpc/64s: Define MASKABLE_RELON_EXCEPTION_PSERIES_OOL
From: Daniel Axtens <[email protected]>
Add a definition provided by mpe and fixed up for 4.4. It doesn't exist for 4.4 and we'd quite like to use it.
--- arch/powerpc/include/asm/exception-64s.h | 6 ++++++ 1 file changed, 6 insertions(+)
arch/powerpc/include/asm/exception-64s.h +6 -0
@@ -597,6 +597,12 @@ label##_relon_hv: \EXCEPTION_PROLOG_1 (PACA_EXGEN ,SOFTEN_NOTEST_HV , vec); \ EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); +#define MASKABLE_RELON_EXCEPTION_PSERIES_OOL (vec, label) \ + .globl label##_relon_pSeries; \ +label##_relon_pSeries: \ + EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_PR, vec); \ + EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_STD) +/* * Our exception common code can be passed various "additions" * to specify the behaviour of interrupts, whether to kick the
Greg Kroah-Hartman
maintainerPATCH 2/15 powerpc/64s: move some exception handlers out of line
In reply to Greg Kroah-HartmanFrom: Daniel Axtens <[email protected]>
(backport only)
We're about to grow the exception handlers, which will make a bunch of them no longer fit within the space available. We move them out of line.
This is a fiddly and error-prone business, so in the interests of reviewability I haven't merged this in with the addition of the entry flush.
--- arch/powerpc/kernel/exceptions-64s.S | 138 ++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 48 deletions(-)
arch/powerpc/kernel/exceptions-64s.S +90 -48
@@ -202,8 +202,8 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE data_access_pSeries: HMT_MEDIUM_PPR_DISCARD SET_SCRATCH0(r13) - EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD, - KVMTEST, 0x300) + EXCEPTION_PROLOG_0(PACA_EXGEN) + b data_access_pSeries_ool . = 0x380 .globl data_access_slb_pSeries
@@ -211,31 +211,15 @@ data_access_slb_pSeries: HMT_MEDIUM_PPR_DISCARD SET_SCRATCH0(r13) EXCEPTION_PROLOG_0(PACA_EXSLB) - EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r3,SPRN_DAR -#ifdef __DISABLED__ - /* Keep that around for when we re-implement dynamic VSIDs */ - cmpdi r3,0 - bge slb_miss_user_pseries -#endif /* __DISABLED__ */ - mfspr r12,SPRN_SRR1 -#ifndef CONFIG_RELOCATABLE - b slb_miss_realmode -#else - /* - * We can't just use a direct branch to slb_miss_realmode - * because the distance from here to there depends on where - * the kernel ends up being put. - */ - mfctr r11 - ld r10,PACAKBASE(r13) - LOAD_HANDLER(r10, slb_miss_realmode) - mtctr r10 - bctr -#endif + b data_access_slb_pSeries_ool - STD_EXCEPTION_PSERIES(0x400, 0x400, instruction_access) + . = 0x400 + .globl instruction_access_pSeries +instruction_access_pSeries: + HMT_MEDIUM_PPR_DISCARD + SET_SCRATCH0(r13) + EXCEPTION_PROLOG_0(PACA_EXGEN) + b instruction_access_pSeries_ool . = 0x480 .globl instruction_access_slb_pSeries
@@ -243,24 +227,7 @@ instruction_access_slb_pSeries: HMT_MEDIUM_PPR_DISCARD SET_SCRATCH0(r13) EXCEPTION_PROLOG_0(PACA_EXSLB) - EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) - std r3,PACA_EXSLB+EX_R3(r13) - mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ -#ifdef __DISABLED__ - /* Keep that around for when we re-implement dynamic VSIDs */ - cmpdi r3,0 - bge slb_miss_user_pseries -#endif /* __DISABLED__ */ - mfspr r12,SPRN_SRR1 -#ifndef CONFIG_RELOCATABLE - b slb_miss_realmode -#else - mfctr r11 - ld r10,PACAKBASE(r13) - LOAD_HANDLER(r10, slb_miss_realmode) - mtctr r10 - bctr -#endif + b instruction_access_slb_pSeries_ool /* We open code these as we can't have a ". = x" (even with * x = "." within a feature section
@@ -291,13 +258,19 @@ hardware_interrupt_hv: KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800) . = 0x900 - .globl decrementer_pSeries -decrementer_pSeries: + .globl decrementer_trampoline +decrementer_trampoline: SET_SCRATCH0(r13) EXCEPTION_PROLOG_0(PACA_EXGEN) b decrementer_ool - STD_EXCEPTION_HV(0x980, 0x982, hdecrementer) + . = 0x980 + .globl hdecrementer_trampoline +hdecrementer_trampoline: + HMT_MEDIUM_PPR_DISCARD; + SET_SCRATCH0(r13); + EXCEPTION_PROLOG_0(PACA_EXGEN) + b hdecrementer_hv MASKABLE_EXCEPTION_PSERIES(0xa00, 0xa00, doorbell_super) KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00)
@@ -545,6 +518,64 @@ machine_check_pSeries_0: KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900) KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982) +/* moved from 0x300 */ + .globl data_access_pSeries_ool +data_access_pSeries_ool: + EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, 0x300) + EXCEPTION_PROLOG_PSERIES_1(data_access_common, EXC_STD) + + .globl data_access_slb_pSeries_ool +data_access_slb_pSeries_ool: + EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380) + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_DAR +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ + mfspr r12,SPRN_SRR1 +#ifndef CONFIG_RELOCATABLE + b slb_miss_realmode +#else + /* + * We can't just use a direct branch to slb_miss_realmode + * because the distance from here to there depends on where + * the kernel ends up being put. + */ + mfctr r11 + ld r10,PACAKBASE(r13) + LOAD_HANDLER(r10, slb_miss_realmode) + mtctr r10 + bctr +#endif + + .globl instruction_access_pSeries_ool +instruction_access_pSeries_ool: + EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, 0x400) + EXCEPTION_PROLOG_PSERIES_1(instruction_access_common, EXC_STD) + + .globl instruction_access_slb_pSeries_ool +instruction_access_slb_pSeries_ool: + EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) + std r3,PACA_EXSLB+EX_R3(r13) + mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ +#ifdef __DISABLED__ + /* Keep that around for when we re-implement dynamic VSIDs */ + cmpdi r3,0 + bge slb_miss_user_pseries +#endif /* __DISABLED__ */ + mfspr r12,SPRN_SRR1 +#ifndef CONFIG_RELOCATABLE + b slb_miss_realmode +#else + mfctr r11 + ld r10,PACAKBASE(r13) + LOAD_HANDLER(r10, slb_miss_realmode) + mtctr r10 + bctr +#endif + #ifdef CONFIG_PPC_DENORMALISATION denorm_assist: BEGIN_FTR_SECTION
@@ -612,6 +643,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) .align 7 /* moved from 0xe00 */ MASKABLE_EXCEPTION_OOL(0x900, decrementer) + STD_EXCEPTION_HV_OOL(0x982, hdecrementer) STD_EXCEPTION_HV_OOL(0xe02, h_data_storage) KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02) STD_EXCEPTION_HV_OOL(0xe22, h_instr_storage)
@@ -894,7 +926,15 @@ hardware_interrupt_relon_hv: STD_RELON_EXCEPTION_PSERIES(0x4600, 0x600, alignment) STD_RELON_EXCEPTION_PSERIES(0x4700, 0x700, program_check) STD_RELON_EXCEPTION_PSERIES(0x4800, 0x800, fp_unavailable) - MASKABLE_RELON_EXCEPTION_PSERIES(0x4900, 0x900, decrementer) + + . = 0x4900 + .globl decrementer_relon_trampoline +decrementer_relon_trampoline: + HMT_MEDIUM_PPR_DISCARD + SET_SCRATCH0(r13) + EXCEPTION_PROLOG_0(PACA_EXGEN) + b decrementer_relon_pSeries + STD_RELON_EXCEPTION_HV(0x4980, 0x982, hdecrementer) MASKABLE_RELON_EXCEPTION_PSERIES(0x4a00, 0xa00, doorbell_super) STD_RELON_EXCEPTION_PSERIES(0x4b00, 0xb00, trap_0b)
@@ -1244,6 +1284,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) __end_handlers: /* Equivalents to the above handlers for relocation-on interrupt vectors */ + MASKABLE_RELON_EXCEPTION_PSERIES_OOL(0x900, decrementer) + STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist) MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
Greg Kroah-Hartman
maintainerPATCH 3/15 powerpc/64s: flush L1D on kernel entry
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
commit f79643787e0a0762d2409b7b8334e83f22d85695 upstream.
IBM Power9 processors can speculatively operate on data in the L1 cache before it has been completely validated, via a way-prediction mechanism. It is not possible for an attacker to determine the contents of impermissible memory using this method, since these systems implement a combination of hardware and software security measures to prevent scenarios where protected data could be leaked.
However these measures don't address the scenario where an attacker induces the operating system to speculatively execute instructions using data that the attacker controls. This can be used for example to speculatively bypass "kernel user access prevention" techniques, as discovered by Anthony Steinhauser of Google's Safeside Project. This is not an attack by itself, but there is a possibility it could be used in conjunction with side-channels or other weaknesses in the privileged code to construct an attack.
This issue can be mitigated by flushing the L1 cache between privilege boundaries of concern. This patch flushes the L1 cache on kernel entry.
This is part of the fix for CVE-2020-4788.
--- Documentation/kernel-parameters.txt | 3 + arch/powerpc/include/asm/exception-64s.h | 9 +++- arch/powerpc/include/asm/feature-fixups.h | 10 ++++ arch/powerpc/include/asm/security_features.h | 4 + arch/powerpc/include/asm/setup.h | 3 + arch/powerpc/kernel/exceptions-64s.S | 38 +++++++++++++++++ arch/powerpc/kernel/setup_64.c | 58 +++++++++++++++++++++++++++ arch/powerpc/kernel/vmlinux.lds.S | 7 +++ arch/powerpc/lib/feature-fixups.c | 54 +++++++++++++++++++++++++ arch/powerpc/platforms/powernv/setup.c | 10 ++++ arch/powerpc/platforms/pseries/setup.c | 4 + 11 files changed, 199 insertions(+), 1 deletion(-)
Documentation/kernel-parameters.txt +3 -0
@@ -2196,6 +2196,7 @@ bytes respectively. Such letter suffixes spec_store_bypass_disable=off [X86] mds=off [X86] tsx_async_abort=off [X86] + no_entry_flush [PPC] auto (default) Mitigate all CPU vulnerabilities, but leave SMT
@@ -2476,6 +2477,8 @@ bytes respectively. Such letter suffixes noefi Disable EFI runtime services support. + no_entry_flush [PPC] Don't flush the L1-D cache when entering the kernel. + noexec [IA-64] noexec [X86]
arch/powerpc/include/asm/exception-64s.h +8 -1
@@ -65,11 +65,18 @@nop ; \ nop +#define ENTRY_FLUSH_SLOT \ + ENTRY_FLUSH_FIXUP_SECTION; \ + nop; \ + nop; \ + nop; +/* * r10 must be free to use, r13 must be paca */ #define INTERRUPT_TO_KERNEL \ - STF_ENTRY_BARRIER_SLOT + STF_ENTRY_BARRIER_SLOT; \ + ENTRY_FLUSH_SLOT/* * Macros for annotating the expected destination of (h)rfid
arch/powerpc/include/asm/feature-fixups.h +10 -0
@@ -200,6 +200,14 @@ label##3: \ FTR_ENTRY_OFFSET 955b-956b; \ .popsection; +#define ENTRY_FLUSH_FIXUP_SECTION \ +957: \ + .pushsection __entry_flush_fixup,"a"; \ + .align 2; \ +958: \ + FTR_ENTRY_OFFSET 957b-958b; \ + .popsection; +#define RFI_FLUSH_FIXUP_SECTION \ 951: \ .pushsection __rfi_flush_fixup,"a"; \
@@ -231,8 +239,10 @@ label##3: \#ifndef __ASSEMBLY__extern long stf_barrier_fallback; +extern long entry_flush_fallback;extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; +extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
arch/powerpc/include/asm/security_features.h +4 -0
@@ -84,12 +84,16 @@ static inline bool security_ftr_enabled(// Software required to flush link stack on context switch #define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull +// The L1-D cache should be flushed when entering the kernel +#define SEC_FTR_L1D_FLUSH_ENTRY 0x0000000000004000ull +// Features enabled by default #define SEC_FTR_DEFAULT \ (SEC_FTR_L1D_FLUSH_HV | \ SEC_FTR_L1D_FLUSH_PR | \ SEC_FTR_BNDS_CHK_SPEC_BAR | \ + SEC_FTR_L1D_FLUSH_ENTRY | \ SEC_FTR_FAVOUR_SECURITY)#endif /* _ASM_POWERPC_SECURITY_FEATURES_H */
arch/powerpc/include/asm/setup.h +3 -0
@@ -38,12 +38,15 @@ enum l1d_flush_type { };void setup_rfi_flush (enum l1d_flush_type ,bool enable); +void setup_entry_flush (bool enable); +void setup_uaccess_flush (bool enable);void do_rfi_flush_fixups (enum l1d_flush_type types);#ifdef CONFIG_PPC_BARRIER_NOSPEC void setup_barrier_nospec (void );#else static inline void setup_barrier_nospec (void ) { };#endif +void do_entry_flush_fixups (enum l1d_flush_type types);void do_barrier_nospec_fixups (bool enable);extern bool barrier_nospec_enabled;
arch/powerpc/kernel/exceptions-64s.S +38 -0
@@ -1712,6 +1712,44 @@ hrfi_flush_fallback: GET_SCRATCH0(r13); hrfid + .globl entry_flush_fallback +entry_flush_fallback: + std r9,PACA_EXRFI+EX_R9(r13) + std r10,PACA_EXRFI+EX_R10(r13) + std r11,PACA_EXRFI+EX_R11(r13) + mfctr r9 + ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) + ld r11,PACA_L1D_FLUSH_SIZE(r13) + srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ + mtctr r11 + DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ + + /* order ld/st prior to dcbt stop all streams with flushing */ + sync + + /* + * The load addresses are at staggered offsets within cachelines, + * which suits some pipelines better (on others it should not + * hurt). + */ +1: + ld r11,(0x80 + 8)*0(r10) + ld r11,(0x80 + 8)*1(r10) + ld r11,(0x80 + 8)*2(r10) + ld r11,(0x80 + 8)*3(r10) + ld r11,(0x80 + 8)*4(r10) + ld r11,(0x80 + 8)*5(r10) + ld r11,(0x80 + 8)*6(r10) + ld r11,(0x80 + 8)*7(r10) + addi r10,r10,0x80*8 + bdnz 1b + + mtctr r9 + ld r9,PACA_EXRFI+EX_R9(r13) + ld r10,PACA_EXRFI+EX_R10(r13) + ld r11,PACA_EXRFI+EX_R11(r13) + blr + /* * Hash table stuff */
arch/powerpc/kernel/setup_64.c +58 -0
92 lines not on this page · raw message
arch/powerpc/kernel/vmlinux.lds.S +7 -0
@@ -81,6 +81,13 @@ SECTIONS } . = ALIGN(8); + __entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) { + __start___entry_flush_fixup = .; + *(__entry_flush_fixup) + __stop___entry_flush_fixup = .; + } + + . = ALIGN(8); __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) { __start___stf_exit_barrier_fixup = .; *(__stf_exit_barrier_fixup)
arch/powerpc/lib/feature-fixups.c +54 -0
60 lines not on this page · raw message
arch/powerpc/platforms/powernv/setup.c +10 -0
@@ -124,12 +124,22 @@ static void pnv_setup_rfi_flush(void) type =L1D_FLUSH_ORI ; } +/* +* 4.4 doesn't support Power9 bare metal, so we don't need to flush +* here - the flush fixes a P9 specific vulnerability. +*/ +security_ftr_clear (SEC_FTR_L1D_FLUSH_ENTRY ); + enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) && \ (security_ftr_enabled (SEC_FTR_L1D_FLUSH_PR ) || \security_ftr_enabled (SEC_FTR_L1D_FLUSH_HV ));setup_rfi_flush (type, enable);setup_count_cache_flush (); + + enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) && +security_ftr_enabled (SEC_FTR_L1D_FLUSH_ENTRY ); +setup_entry_flush (enable); }static void __init pnv_setup_arch (void )
arch/powerpc/platforms/pseries/setup.c +4 -0
@@ -584,6 +584,10 @@ void pseries_setup_rfi_flush(void)setup_rfi_flush (types, enable);setup_count_cache_flush (); + + enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) && +security_ftr_enabled (SEC_FTR_L1D_FLUSH_ENTRY ); +setup_entry_flush (enable); }static void __init pSeries_setup_arch (void )
Greg Kroah-Hartman
maintainerPATCH 4/15 powerpc: Add a framework for user access tracking
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
Backported from commit de78a9c42a79 ("powerpc: Add a framework for Kernel Userspace Access Protection"). Here we don't try to add the KUAP framework, we just want the helper functions because we want to put uaccess flush helpers in them.
In terms of fixes, we don't need commit 1d8f739b07bd ("powerpc/kuap:
Fix set direction in allow/prevent_user_access()") as we don't have real KUAP. Likewise as all our allows are noops and all our prevents are just flushes, we don't need commit 9dc086f1e9ef ("powerpc/futex:
Fix incorrect user access blocking") The other 2 fixes we do need.
The original description is:
This patch implements a framework for Kernel Userspace Access Protection.
Then subarches will have the possibility to provide their own implementation by providing setup_kuap() and allow/prevent_user_access().
Some platforms will need to know the area accessed and whether it is accessed from read, write or both. Therefore source, destination and size and handed over to the two functions.
mpe: Rename to allow/prevent rather than unlock/lock, and add read/write wrappers. Drop the 32-bit code for now until we have an implementation for it. Add kuap to pt_regs for 64-bit as well as 32-bit. Don't split strings, use pr_crit_ratelimited().
--- arch/powerpc/include/asm/futex.h | 4 +++ arch/powerpc/include/asm/kup.h | 36 ++++++++++++++++++++++++++++++ arch/powerpc/include/asm/uaccess.h | 38 +++++++++++++++++++++++++------- arch/powerpc/lib/checksum_wrappers_64.c | 4 +++ 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 arch/powerpc/include/asm/kup.h
arch/powerpc/include/asm/futex.h +4 -0
@@ -36,6 +36,7 @@ static inline int arch_futex_atomic_op_i {int oldval =0 , ret; +allow_write_to_user (uaddr,sizeof (*uaddr));pagefault_disable ();switch (op) {
@@ -62,6 +63,7 @@ static inline int arch_futex_atomic_op_i *oval = oldval; +prevent_write_to_user (uaddr,sizeof (*uaddr));return ret; }
@@ -75,6 +77,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,if (!access_ok (VERIFY_WRITE , uaddr,sizeof (u32)))return -EFAULT ; +allow_write_to_user (uaddr,sizeof (*uaddr)); __asm__ __volatile__ ( PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
@@ -97,6 +100,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, : "cc", "memory"); *uval = prev; +prevent_write_to_user (uaddr,sizeof (*uaddr));return ret; }
arch/powerpc/include/asm/kup.h new file +36 -0
@@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_KUP_H_ +#define _ASM_POWERPC_KUP_H_ + +#ifndef __ASSEMBLY__ + +#include <asm/pgtable.h> + +static inline void allow_user_access (void __user *to,const void __user *from, +unsigned long size) { } +static inline void prevent_user_access (void __user *to,const void __user *from, +unsigned long size) { } + +static inline void allow_read_from_user (const void __user *from,unsigned long size) +{ +allow_user_access (NULL , from, size); +} + +static inline void allow_write_to_user (void __user *to,unsigned long size) +{ +allow_user_access (to,NULL , size); +} + +static inline void prevent_read_from_user (const void __user *from,unsigned long size) +{ +prevent_user_access (NULL , from, size); +} + +static inline void prevent_write_to_user (void __user *to,unsigned long size) +{ +prevent_user_access (to,NULL , size); +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_KUP_H_ */
arch/powerpc/include/asm/uaccess.h +30 -8
@@ -9,6 +9,7 @@#include <asm/asm-compat.h> #include <asm/processor.h> #include <asm/page.h> +#include <asm/kup.h> #define VERIFY_READ 0#define VERIFY_WRITE 1
@@ -164,6 +165,7 @@ extern long __put_user_bad(void);#define __put_user_size (x, ptr, size, retval) \ do { \ retval = 0; \ + allow_write_to_user(ptr, size); \ switch (size) { \ case 1: __put_user_asm(x, ptr, retval, "stb"); break; \ case 2: __put_user_asm(x, ptr, retval, "sth"); break; \
@@ -171,6 +173,7 @@ do { \case 8 :__put_user_asm2 (x, ptr, retval);break ; \default :__put_user_bad (); \ } \ +prevent_write_to_user (ptr, size); \ }while (0 ) #define __put_user_nocheck(x, ptr, size) \
@@ -252,6 +255,7 @@ do { \__chk_user_ptr (ptr); \if (size >sizeof (x)) \ (x) =__get_user_bad (); \ +allow_read_from_user (ptr, size); \switch (size) { \case 1 :__get_user_asm (x, ptr, retval,"lbz" );break ; \case 2 :__get_user_asm (x, ptr, retval,"lhz" );break ; \
@@ -259,6 +263,7 @@ do { \case 8 :__get_user_asm2 (x, ptr, retval);break ; \default : (x) =__get_user_bad (); \ } \ +prevent_read_from_user (ptr, size); \ }while (0 ) #define __get_user_nocheck(x, ptr, size) \
@@ -328,9 +333,14 @@ extern unsigned long __copy_tofrom_user(static inline unsigned long copy_from_user (void *to,const void __user *from,unsigned long n) { +unsigned long ret; +if (likely (access_ok (VERIFY_READ , from, n))) { +allow_user_access (to, from, n);barrier_nospec (); -return __copy_tofrom_user ((__force void __user *)to, from, n); + ret =__copy_tofrom_user ((__force void __user *)to, from, n); +prevent_user_access (to, from, n); +return ret; }memset (to,0 , n);return n;
@@ -361,8 +371,9 @@ extern unsigned long copy_in_user(void _static inline unsigned long __copy_from_user_inatomic (void *to,const void __user *from,unsigned long n) { +unsigned long ret;if (__builtin_constant_p (n) && (n <=8 )) { -unsigned long ret =1 ; + ret =1 ;switch (n) {case 1 :
@@ -387,14 +398,18 @@ static inline unsigned long __copy_from_ }barrier_nospec (); -return __copy_tofrom_user ((__force void __user *)to, from, n); +allow_read_from_user (from, n); + ret =__copy_tofrom_user ((__force void __user *)to, from, n); +prevent_read_from_user (from, n); +return ret; }static inline unsigned long __copy_to_user_inatomic (void __user *to,const void *from,unsigned long n) { +unsigned long ret;if (__builtin_constant_p (n) && (n <=8 )) { -unsigned long ret =1 ; + ret =1 ;switch (n) {case 1 :
@@ -414,7 +429,10 @@ static inline unsigned long __copy_to_usreturn 0 ; } -return __copy_tofrom_user (to, (__force const void __user *)from, n); +allow_write_to_user (to, n); + ret =__copy_tofrom_user (to, (__force const void __user *)from, n); +prevent_write_to_user (to, n); +return ret; } static inline unsigned long __copy_from_user(void *to,
@@ -435,10 +453,14 @@ extern unsigned long __clear_user(void _static inline unsigned long clear_user (void __user *addr,unsigned long size) { +unsigned long ret = size;might_fault (); -if (likely (access_ok (VERIFY_WRITE , addr, size))) -return __clear_user (addr, size); -return size; +if (likely (access_ok (VERIFY_WRITE , addr, size))) { +allow_write_to_user (addr, size); + ret =__clear_user (addr, size); +prevent_write_to_user (addr, size); + } +return ret; }extern long strncpy_from_user (char *dst,const char __user *src,long count);
arch/powerpc/lib/checksum_wrappers_64.c +4 -0
@@ -29,6 +29,7 @@ __wsum csum_and_copy_from_user(const voiunsigned int csum;might_sleep (); +allow_read_from_user (src, len); *err_ptr =0 ;
@@ -60,6 +61,7 @@ __wsum csum_and_copy_from_user(const voi } out: +prevent_read_from_user (src, len);return (__force __wsum )csum; }EXPORT_SYMBOL (csum_and_copy_from_user);
@@ -70,6 +72,7 @@ __wsum csum_and_copy_to_user(const voidunsigned int csum;might_sleep (); +allow_write_to_user (dst, len); *err_ptr =0 ;
@@ -97,6 +100,7 @@ __wsum csum_and_copy_to_user(const void } out: +prevent_write_to_user (dst, len);return (__force __wsum )csum; }EXPORT_SYMBOL (csum_and_copy_to_user);
Greg Kroah-Hartman
maintainerPATCH 5/15 powerpc: Implement user_access_begin and friends
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit 5cd623333e7cf4e3a334c70529268b65f2a6c2c7 upstream.
Today, when a function like strncpy_from_user() is called, the userspace access protection is de-activated and re-activated for every word read.
By implementing user_access_begin and friends, the protection is de-activated at the beginning of the copy and re-activated at the end.
Implement user_access_begin(), user_access_end() and unsafe_get_user(), unsafe_put_user() and unsafe_copy_to_user()
For the time being, we keep user_access_save() and user_access_restore() as nops.
--- arch/powerpc/include/asm/uaccess.h | 60 ++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 14 deletions(-)
arch/powerpc/include/asm/uaccess.h +46 -14
@@ -106,9 +106,14 @@ struct exception_table_entry { __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))#define __get_user (x, ptr) \ - __get_user_nocheck((x), (ptr), sizeof(*(ptr))) + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), true)#define __put_user (x, ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), true) + +#define __get_user_allowed (x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), false) +#define __put_user_allowed (x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), false)#define __get_user_inatomic (x, ptr) \ __get_user_nosleep((x), (ptr), sizeof(*(ptr)))
@@ -162,10 +167,9 @@ extern long __put_user_bad(void); : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))#endif /* __powerpc64__ */ -#define __put_user_size (x, ptr, size, retval) \ +#define __put_user_size_allowed (x, ptr, size, retval) \ do { \ retval = 0; \ - allow_write_to_user(ptr, size); \ switch (size) { \ case 1: __put_user_asm(x, ptr, retval, "stb"); break; \ case 2: __put_user_asm(x, ptr, retval, "sth"); break; \
@@ -173,17 +177,26 @@ do { \case 8 :__put_user_asm2 (x, ptr, retval);break ; \default :__put_user_bad (); \ } \ +} while (0) + +#define __put_user_size (x, ptr, size, retval) \ +do { \ + allow_write_to_user(ptr, size); \ + __put_user_size_allowed(x, ptr, size, retval); \ prevent_write_to_user(ptr, size); \ } while (0) -#define __put_user_nocheck (x, ptr, size) \ +#define __put_user_nocheck (x, ptr, size, do_allow) \ ({ \ long __pu_err; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ if (!is_kernel_addr((unsigned long)__pu_addr)) \ might_fault(); \ __chk_user_ptr(ptr); \ - __put_user_size((x), __pu_addr, (size), __pu_err); \ + if (do_allow) \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ + else \ + __put_user_size_allowed((x), __pu_addr, (size), __pu_err); \ __pu_err; \ })
@@ -249,13 +262,12 @@ extern long __get_user_bad(void); : "b" (addr), "i" (-EFAULT), "0" (err))#endif /* __powerpc64__ */ -#define __get_user_size (x, ptr, size, retval) \ +#define __get_user_size_allowed (x, ptr, size, retval) \ do { \ retval = 0; \ __chk_user_ptr(ptr); \ if (size > sizeof(x)) \ (x) = __get_user_bad(); \ - allow_read_from_user(ptr, size); \ switch (size) { \ case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \ case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \
@@ -263,10 +275,16 @@ do { \case 8 :__get_user_asm2 (x, ptr, retval);break ; \default : (x) =__get_user_bad (); \ } \ +} while (0) + +#define __get_user_size (x, ptr, size, retval) \ +do { \ + allow_read_from_user(ptr, size); \ + __get_user_size_allowed(x, ptr, size, retval); \ prevent_read_from_user(ptr, size); \ } while (0) -#define __get_user_nocheck (x, ptr, size) \ +#define __get_user_nocheck (x, ptr, size, do_allow) \ ({ \ long __gu_err; \ unsigned long __gu_val; \
@@ -275,7 +293,10 @@ do { \if (!is_kernel_addr ((unsigned long )__gu_addr)) \might_fault (); \barrier_nospec (); \ -__get_user_size (__gu_val, __gu_addr, (size), __gu_err); \ +if (do_allow) \ +__get_user_size (__gu_val, __gu_addr, (size), __gu_err); \ +else \ +__get_user_size_allowed (__gu_val, __gu_addr, (size), __gu_err); \ (x) = (__typeof__ (*(ptr )))__gu_val; \ __gu_err; \ })
@@ -408,21 +429,22 @@ static inline unsigned long __copy_to_us const void *from, unsigned long n) { unsigned long ret; +if (__builtin_constant_p (n) && (n <=8 )) { ret =1 ;switch (n) {case 1 : -__put_user_size (*(u8 *)from, (u8 __user *)to,1 , ret); +__put_user_size_allowed (*(u8 *)from, (u8 __user *)to,1 , ret);break ;case 2 : -__put_user_size (*(u16 *)from, (u16 __user *)to,2 , ret); +__put_user_size_allowed (*(u16 *)from, (u16 __user *)to,2 , ret);break ;case 4 : -__put_user_size (*(u32 *)from, (u32 __user *)to,4 , ret); +__put_user_size_allowed (*(u32 *)from, (u32 __user *)to,4 , ret);break ;case 8 : -__put_user_size (*(u64 *)from, (u64 __user *)to,8 , ret); +__put_user_size_allowed (*(u64 *)from, (u64 __user *)to,8 , ret);break ; }if (ret ==0 )
@@ -467,6 +489,16 @@ extern long strncpy_from_user(char *dst,extern __must_check long strlen_user (const char __user *str);extern __must_check long strnlen_user (const char __user *str,long n); + +#define user_access_begin () do { } while (0) +#define user_access_end () prevent_user_access(NULL, NULL, ~0ul) + +#define unsafe_op_wrap (op, err) do { if (unlikely(op)) goto err; } while (0) +#define unsafe_get_user (x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e) +#define unsafe_put_user (x, p, e) unsafe_op_wrap(__put_user_allowed(x, p), e) +#define unsafe_copy_to_user (d, s, l, e) \ + unsafe_op_wrap(__copy_to_user_inatomic(d, s, l), e) +#endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */
Greg Kroah-Hartman
maintainerPATCH 6/15 powerpc: Fix __clear_user() with KUAP enabled
In reply to Greg Kroah-HartmanFrom: Andrew Donnellan <[email protected]>
commit 61e3acd8c693a14fc69b824cb5b08d02cb90a6e7 upstream.
The KUAP implementation adds calls in clear_user() to enable and disable access to userspace memory. However, it doesn't add these to __clear_user(), which is used in the ptrace regset code.
As there's only one direct user of __clear_user() (the regset code), and the time taken to set the AMR for KUAP purposes is going to dominate the cost of a quick access_ok(), there's not much point having a separate path.
Rename __clear_user() to __arch_clear_user(), and make __clear_user() just call clear_user().
--- arch/powerpc/include/asm/uaccess.h | 9 +++++++-- arch/powerpc/kernel/ppc_ksyms.c | 3 +++ arch/powerpc/lib/string.S | 2 +- arch/powerpc/lib/string_64.S | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-)
arch/powerpc/include/asm/uaccess.h +7 -2
@@ -471,7 +471,7 @@ static inline unsigned long __copy_to_usreturn __copy_to_user_inatomic (to, from, size); } -extern unsigned long __clear_user (void __user *addr,unsigned long size); +unsigned long __arch_clear_user (void __user *addr,unsigned long size);static inline unsigned long clear_user (void __user *addr,unsigned long size) {
@@ -479,12 +479,17 @@ static inline unsigned long clear_user(vmight_fault ();if (likely (access_ok (VERIFY_WRITE , addr, size))) {allow_write_to_user (addr, size); - ret =__clear_user (addr, size); + ret =__arch_clear_user (addr, size);prevent_write_to_user (addr, size); }return ret; } +static inline unsigned long __clear_user (void __user *addr,unsigned long size) +{ +return clear_user (addr, size); +} +extern long strncpy_from_user (char *dst,const char __user *src,long count);extern __must_check long strlen_user (const char __user *str);extern __must_check long strnlen_user (const char __user *str,long n);
arch/powerpc/kernel/ppc_ksyms.c +3 -0
@@ -5,6 +5,7 @@#include <asm/switch_to.h> #include <asm/cacheflush.h> #include <asm/epapr_hcalls.h> +#include <asm/uaccess.h> EXPORT_SYMBOL (flush_dcache_range);EXPORT_SYMBOL (flush_icache_range);
@@ -43,3 +44,5 @@ EXPORT_SYMBOL(epapr_hypercall_start);#endif EXPORT_SYMBOL (current_stack_pointer); + +EXPORT_SYMBOL (__arch_clear_user);
arch/powerpc/lib/string.S +1 -1
@@ -122,7 +122,7 @@ _GLOBAL(memchr) blr #ifdef CONFIG_PPC32 -_GLOBAL(__clear_user) +_GLOBAL(__arch_clear_user) addi r6,r3,-4 li r3,0 li r5,0
arch/powerpc/lib/string_64.S +2 -2
@@ -27,7 +27,7 @@ PPC64_CACHES: .section ".text" /** - * __clear_user: - Zero a block of memory in user space, with less checking. + * __arch_clear_user: - Zero a block of memory in user space, with less checking. * @to: Destination address, in user space. * @n: Number of bytes to zero. *
@@ -77,7 +77,7 @@ err3; stb r0,0(r3) mr r3,r4 blr -_GLOBAL_TOC(__clear_user) +_GLOBAL_TOC(__arch_clear_user) cmpdi r4,32 neg r6,r3 li r0,0
Greg Kroah-Hartman
maintainerPATCH 7/15 powerpc/uaccess: Evaluate macro arguments once, before user access is allowed
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
commit d02f6b7dab8228487268298ea1f21081c0b4b3eb upstream.
get/put_user() can be called with nontrivial arguments. fs/proc/page.c has a good example:
if (put_user(stable_page_flags(ppage), out)) {stable_page_flags() is quite a lot of code, including spin locks in the page allocator.
Ensure these arguments are evaluated before user access is allowed.
This improves security by reducing code with access to userspace, but it also fixes a PREEMPT bug with KUAP on powerpc/64s:stable_page_flags() is currently called with AMR set to allow writes, it ends up calling spin_unlock(), which can call preempt_schedule. But the task switch code can not be called with AMR set (it relies on interrupts saving the register), so this blows up.
It's fine if the code inside allow_user_access() is preemptible, because a timer or IPI will save the AMR, but it's not okay to explicitly cause a reschedule.
--- arch/powerpc/include/asm/uaccess.h | 49 ++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 14 deletions(-)
arch/powerpc/include/asm/uaccess.h +35 -14
@@ -190,13 +190,17 @@ do { \ ({ \long __pu_err; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ +__typeof__ (size) __pu_size = (size); \ + \if (!is_kernel_addr ((unsigned long )__pu_addr)) \might_fault (); \ -__chk_user_ptr (ptr); \ +__chk_user_ptr (__pu_addr); \if (do_allow) \ -__put_user_size ((x), __pu_addr, (size), __pu_err); \ +__put_user_size (__pu_val, __pu_addr, __pu_size, __pu_err); \else \ -__put_user_size_allowed ((x), __pu_addr, (size), __pu_err); \ +__put_user_size_allowed (__pu_val, __pu_addr, __pu_size, __pu_err); \ + \ __pu_err; \ })
@@ -204,9 +208,13 @@ do { \ ({ \long __pu_err = -EFAULT ; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ +__typeof__ (size) __pu_size = (size); \ + \might_fault (); \ -if (access_ok (VERIFY_WRITE , __pu_addr, size)) \ -__put_user_size ((x), __pu_addr, (size), __pu_err); \ +if (access_ok (VERIFY_WRITE , __pu_addr, __pu_size)) \ +__put_user_size (__pu_val, __pu_addr, __pu_size, __pu_err); \ + \ __pu_err; \ })
@@ -214,8 +222,12 @@ do { \ ({ \long __pu_err; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ -__chk_user_ptr (ptr); \ -__put_user_size ((x), __pu_addr, (size), __pu_err); \ + __typeof__(*(ptr)) __pu_val = (x); \ +__typeof__ (size) __pu_size = (size); \ + \ +__chk_user_ptr (__pu_addr); \ +__put_user_size (__pu_val, __pu_addr, __pu_size, __pu_err); \ + \ __pu_err; \ })
@@ -289,15 +301,18 @@ do { \long __gu_err; \unsigned long __gu_val; \ __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ -__chk_user_ptr (ptr); \ +__typeof__ (size) __gu_size = (size); \ + \ +__chk_user_ptr (__gu_addr); \if (!is_kernel_addr ((unsigned long )__gu_addr)) \might_fault (); \barrier_nospec (); \if (do_allow) \ -__get_user_size (__gu_val, __gu_addr, (size), __gu_err); \ +__get_user_size (__gu_val, __gu_addr, __gu_size, __gu_err); \else \ -__get_user_size_allowed (__gu_val, __gu_addr, (size), __gu_err); \ +__get_user_size_allowed (__gu_val, __gu_addr, __gu_size, __gu_err); \ (x) = (__typeof__ (*(ptr )))__gu_val; \ + \ __gu_err; \ })
@@ -322,12 +337,15 @@ do { \long __gu_err = -EFAULT ; \unsigned long __gu_val =0 ; \ __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ +__typeof__ (size) __gu_size = (size); \ + \might_fault (); \ -if (access_ok (VERIFY_READ , __gu_addr, (size))) { \ +if (access_ok (VERIFY_READ , __gu_addr, __gu_size)) { \barrier_nospec (); \ -__get_user_size (__gu_val, __gu_addr, (size), __gu_err); \ +__get_user_size (__gu_val, __gu_addr, __gu_size, __gu_err); \ } \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ + \ __gu_err; \ })
@@ -336,10 +354,13 @@ do { \long __gu_err; \unsigned long __gu_val; \ __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ -__chk_user_ptr (ptr); \ +__typeof__ (size) __gu_size = (size); \ + \ +__chk_user_ptr (__gu_addr); \barrier_nospec (); \ -__get_user_size (__gu_val, __gu_addr, (size), __gu_err); \ +__get_user_size (__gu_val, __gu_addr, __gu_size, __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ + \ __gu_err; \ })
Greg Kroah-Hartman
maintainerPATCH 8/15 powerpc/64s: flush L1D after user accesses
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
commit 9a32a7e78bd0cd9a9b6332cbdc345ee5ffd0c5de upstream.
IBM Power9 processors can speculatively operate on data in the L1 cache before it has been completely validated, via a way-prediction mechanism. It is not possible for an attacker to determine the contents of impermissible memory using this method, since these systems implement a combination of hardware and software security measures to prevent scenarios where protected data could be leaked.
However these measures don't address the scenario where an attacker induces the operating system to speculatively execute instructions using data that the attacker controls. This can be used for example to speculatively bypass "kernel user access prevention" techniques, as discovered by Anthony Steinhauser of Google's Safeside Project. This is not an attack by itself, but there is a possibility it could be used in conjunction with side-channels or other weaknesses in the privileged code to construct an attack.
This issue can be mitigated by flushing the L1 cache between privilege boundaries of concern. This patch flushes the L1 cache after user accesses.
This is part of the fix for CVE-2020-4788.
--- Documentation/kernel-parameters.txt | 4 + arch/powerpc/include/asm/book3s/64/kup-radix.h | 23 ++++++ arch/powerpc/include/asm/feature-fixups.h | 9 ++ arch/powerpc/include/asm/kup.h | 4 + arch/powerpc/include/asm/security_features.h | 3 arch/powerpc/include/asm/setup.h | 1 arch/powerpc/kernel/exceptions-64s.S | 86 +++++++------------------ arch/powerpc/kernel/ppc_ksyms.c | 7 ++ arch/powerpc/kernel/setup_64.c | 80 +++++++++++++++++++++++ arch/powerpc/kernel/vmlinux.lds.S | 7 ++ arch/powerpc/lib/feature-fixups.c | 50 ++++++++++++++ arch/powerpc/platforms/powernv/setup.c | 7 +- arch/powerpc/platforms/pseries/setup.c | 4 + 13 files changed, 224 insertions(+), 61 deletions(-) create mode 100644 arch/powerpc/include/asm/book3s/64/kup-radix.h
Documentation/kernel-parameters.txt +4 -0
@@ -2197,6 +2197,7 @@ bytes respectively. Such letter suffixes mds=off [X86] tsx_async_abort=off [X86] no_entry_flush [PPC] + no_uaccess_flush [PPC] auto (default) Mitigate all CPU vulnerabilities, but leave SMT
@@ -2521,6 +2522,9 @@ bytes respectively. Such letter suffixes nospec_store_bypass_disable [HW] Disable all mitigations for the Speculative Store Bypass vulnerability + no_uaccess_flush + [PPC] Don't flush the L1-D cache after accessing user data. + noxsave [BUGS=X86] Disables x86 extended register state save and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state.
arch/powerpc/include/asm/book3s/64/kup-radix.h new file +23 -0
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H +#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H +#include <linux/jump_label.h> + +DECLARE_STATIC_KEY_FALSE (uaccess_flush_key); + +/* Prototype for function defined in exceptions-64s.S */ +void do_uaccess_flush (void ); + +static __always_inline void allow_user_access(void __user *to, const void __user *from, +unsigned long size) +{ +} + +static inline void prevent_user_access (void __user *to,const void __user *from, +unsigned long size) +{ +if (static_branch_unlikely (&uaccess_flush_key)) +do_uaccess_flush (); +} + +#endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */
arch/powerpc/include/asm/feature-fixups.h +9 -0
@@ -200,6 +200,14 @@ label##3: \ FTR_ENTRY_OFFSET 955b-956b; \ .popsection; +#define UACCESS_FLUSH_FIXUP_SECTION \ +959: \ + .pushsection __uaccess_flush_fixup,"a"; \ + .align 2; \ +960: \ + FTR_ENTRY_OFFSET 959b-960b; \ + .popsection; +#define ENTRY_FLUSH_FIXUP_SECTION \ 957: \ .pushsection __entry_flush_fixup,"a"; \
@@ -242,6 +250,7 @@ extern long stf_barrier_fallback;extern long entry_flush_fallback;extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; +extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
arch/powerpc/include/asm/kup.h +4 -0
@@ -6,10 +6,14 @@#include <asm/pgtable.h> +#ifdef CONFIG_PPC_BOOK3S_64 +#include <asm/book3s/64/kup-radix.h> +#else static inline void allow_user_access (void __user *to,const void __user *from,unsigned long size) { }static inline void prevent_user_access (void __user *to,const void __user *from,unsigned long size) { } +#endif /* CONFIG_PPC_BOOK3S_64 */ static inline void allow_read_from_user (const void __user *from,unsigned long size) {
arch/powerpc/include/asm/security_features.h +3 -0
@@ -87,6 +87,8 @@ static inline bool security_ftr_enabled(// The L1-D cache should be flushed when entering the kernel #define SEC_FTR_L1D_FLUSH_ENTRY 0x0000000000004000ull +// The L1-D cache should be flushed after user accesses from the kernel +#define SEC_FTR_L1D_FLUSH_UACCESS 0x0000000000008000ull// Features enabled by default #define SEC_FTR_DEFAULT \
@@ -94,6 +96,7 @@ static inline bool security_ftr_enabled( SEC_FTR_L1D_FLUSH_PR | \ SEC_FTR_BNDS_CHK_SPEC_BAR | \ SEC_FTR_L1D_FLUSH_ENTRY | \ + SEC_FTR_L1D_FLUSH_UACCESS | \ SEC_FTR_FAVOUR_SECURITY)#endif /* _ASM_POWERPC_SECURITY_FEATURES_H */
arch/powerpc/include/asm/setup.h +1 -0
@@ -46,6 +46,7 @@ void setup_barrier_nospec(void);#else static inline void setup_barrier_nospec (void ) { };#endif +void do_uaccess_flush_fixups (enum l1d_flush_type types);void do_entry_flush_fixups (enum l1d_flush_type types);void do_barrier_nospec_fixups (bool enable);extern bool barrier_nospec_enabled;
arch/powerpc/kernel/exceptions-64s.S +26 -60
120 lines not on this page · raw message
arch/powerpc/kernel/ppc_ksyms.c +7 -0
@@ -6,6 +6,9 @@#include <asm/cacheflush.h> #include <asm/epapr_hcalls.h> #include <asm/uaccess.h> +#ifdef CONFIG_PPC64 +#include <asm/book3s/64/kup-radix.h> +#endif EXPORT_SYMBOL (flush_dcache_range);EXPORT_SYMBOL (flush_icache_range);
@@ -46,3 +49,7 @@ EXPORT_SYMBOL(epapr_hypercall_start);EXPORT_SYMBOL (current_stack_pointer);EXPORT_SYMBOL (__arch_clear_user); + +#ifdef CONFIG_PPC64 +EXPORT_SYMBOL (do_uaccess_flush); +#endif
arch/powerpc/kernel/setup_64.c +80 -0
118 lines not on this page · raw message
arch/powerpc/kernel/vmlinux.lds.S +7 -0
@@ -81,6 +81,13 @@ SECTIONS } . = ALIGN(8); + __uaccess_flush_fixup : AT(ADDR(__uaccess_flush_fixup) - LOAD_OFFSET) { + __start___uaccess_flush_fixup = .; + *(__uaccess_flush_fixup) + __stop___uaccess_flush_fixup = .; + } + + . = ALIGN(8); __entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) { __start___entry_flush_fixup = .; *(__entry_flush_fixup)
arch/powerpc/lib/feature-fixups.c +50 -0
56 lines not on this page · raw message
arch/powerpc/platforms/powernv/setup.c +6 -1
@@ -126,9 +126,10 @@ static void pnv_setup_rfi_flush(void)/* * 4.4 doesn't support Power9 bare metal, so we don't need to flush -* here - the flush fixes a P9 specific vulnerability. +* here - the flushes fix a P9 specific vulnerability. */ security_ftr_clear (SEC_FTR_L1D_FLUSH_ENTRY ); +security_ftr_clear (SEC_FTR_L1D_FLUSH_UACCESS ); enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \
@@ -140,6 +141,10 @@ static void pnv_setup_rfi_flush(void) enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) &&security_ftr_enabled (SEC_FTR_L1D_FLUSH_ENTRY );setup_entry_flush (enable); + + enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) && +security_ftr_enabled (SEC_FTR_L1D_FLUSH_UACCESS ); +setup_uaccess_flush (enable); }static void __init pnv_setup_arch (void )
arch/powerpc/platforms/pseries/setup.c +4 -0
@@ -588,6 +588,10 @@ void pseries_setup_rfi_flush(void) enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) &&security_ftr_enabled (SEC_FTR_L1D_FLUSH_ENTRY );setup_entry_flush (enable); + + enable =security_ftr_enabled (SEC_FTR_FAVOUR_SECURITY ) && +security_ftr_enabled (SEC_FTR_L1D_FLUSH_UACCESS ); +setup_uaccess_flush (enable); }static void __init pSeries_setup_arch (void )
Greg Kroah-Hartman
maintainerPATCH 9/15 i2c: imx: Fix external abort on interrupt in exit paths
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit e50e4f0b85be308a01b830c5fbdffc657e1a6dd0 upstream
If interrupt comes late, during probe error path or device remove (could be triggered with CONFIG_DEBUG_SHIRQ), the interrupt handler i2c_imx_isr() will access registers with the clock being disabled. This leads to external abort on non-linefetch on Toradex Colibri VF50 module (with Vybrid VF5xx):
Unhandled fault: external abort on non-linefetch (0x1008) at 0x8882d003
Internal error: : 1008 [#1] ARM
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 5.7.0 #607
Hardware name: Freescale Vybrid VF5xx/VF6xx (Device Tree)
(i2c_imx_isr) from [<8017009c>] (free_irq+0x25c/0x3b0)
(free_irq) from [<805844ec>] (release_nodes+0x178/0x284)
(release_nodes) from [<80580030>] (really_probe+0x10c/0x348)
(really_probe) from [<80580380>] (driver_probe_device+0x60/0x170)
(driver_probe_device) from [<80580630>] (device_driver_attach+0x58/0x60)
(device_driver_attach) from [<805806bc>] (__driver_attach+0x84/0xc0)
(__driver_attach) from [<8057e228>] (bus_for_each_dev+0x68/0xb4)
(bus_for_each_dev) from [<8057f3ec>] (bus_add_driver+0x144/0x1ec)
(bus_add_driver) from [<80581320>] (driver_register+0x78/0x110)
(driver_register) from [<8010213c>] (do_one_initcall+0xa8/0x2f4)
(do_one_initcall) from [<80c0100c>] (kernel_init_freeable+0x178/0x1dc)
(kernel_init_freeable) from [<80807048>] (kernel_init+0x8/0x110)
(kernel_init) from [<80100114>] (ret_from_fork+0x14/0x20)Additionally, the i2c_imx_isr() could wake up the wait queue (imx_i2c_struct->queue) before its initialization happens.
The resource-managed framework should not be used for interrupt handling, because the resource will be released too late - after disabling clocks. The interrupt handler is not prepared for such case.
--- drivers/i2c/busses/i2c-imx.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/i2c/busses/i2c-imx.c +16 -9
@@ -1093,20 +1093,20 @@ static int i2c_imx_probe(struct platform goto clk_disable; } -/* Request IRQ */ - ret =devm_request_irq (&pdev->dev, irq, i2c_imx_isr,0 , - pdev->name, i2c_imx); -if (ret) { -dev_err (&pdev->dev,"can't claim irq %d\n" , irq); - goto clk_disable; - } -/* Init queue */ init_waitqueue_head (&i2c_imx->queue);/* Set up adapter data */ i2c_set_adapdata (&i2c_imx->adapter, i2c_imx); +/* Request IRQ */ + ret =request_threaded_irq (irq, i2c_imx_isr,NULL ,0 , + pdev->name, i2c_imx); +if (ret) { +dev_err (&pdev->dev,"can't claim irq %d\n" , irq); + goto clk_disable; + } +/* Set up clock divider */ i2c_imx->bitrate =IMX_I2C_BIT_RATE ; ret = of_property_read_u32(pdev->dev.of_node,
@@ -1125,7 +1125,7 @@ static int i2c_imx_probe(struct platform ret =i2c_add_numbered_adapter (&i2c_imx->adapter);if (ret <0 ) {dev_err (&pdev->dev,"registration failed\n" ); - goto clk_disable; + goto clk_free_irq; }/* Set up platform driver data */
@@ -1143,6 +1143,8 @@ static int i2c_imx_probe(struct platformreturn 0 ;/* Return OK */ +clk_free_irq: +free_irq (irq, i2c_imx); clk_disable:clk_disable_unprepare (i2c_imx->clk);return ret;
@@ -1151,6 +1153,7 @@ clk_disable:static int i2c_imx_remove (struct platform_device *pdev) {struct imx_i2c_struct *i2c_imx =platform_get_drvdata (pdev); +int irq;/* remove adapter */ dev_dbg (&i2c_imx->adapter.dev,"adapter removed\n" );
@@ -1165,6 +1168,10 @@ static int i2c_imx_remove(struct platforimx_i2c_write_reg (0 , i2c_imx,IMX_I2C_I2CR );imx_i2c_write_reg (0 , i2c_imx,IMX_I2C_I2SR ); + irq =platform_get_irq (pdev,0 ); +if (irq >=0 ) +free_irq (irq, i2c_imx); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 10/15 xfs: catch inode allocation state mismatch corruption
In reply to Greg Kroah-HartmanFrom: Dave Chinner <[email protected]>
commit ee457001ed6c6f31ddad69c24c1da8f377d8472d upstream
We recently came across a V4 filesystem causing memory corruption due to a newly allocated inode being setup twice and being added to the superblock inode list twice. From code inspection, the only way this could happen is if a newly allocated inode was not marked as free on disk (i.e. di_mode wasn't zero).
Running the metadump on an upstream debug kernel fails during inode allocation like so:
XFS: Assertion failed: ip->i_d.di_nblocks == 0, file: fs/xfs/xfs_inod= e.c, line: 838
------------[ cut here ]------------ kernel BUG at fs/xfs/xfs_message.c:114! invalid opcode: 0000 [#1] PREEMPT SMP CPU: 11 PID: 3496 Comm: mkdir Not tainted 4.16.0-rc5-dgc #442 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/0= 1/2014 RIP: 0010:assfail+0x28/0x30 RSP: 0018:ffffc9000236fc80 EFLAGS: 00010202 RAX: 00000000ffffffea RBX: 0000000000004000 RCX: 0000000000000000 RDX: 00000000ffffffc0 RSI: 000000000000000a RDI: ffffffff8227211b RBP: ffffc9000236fce8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000bec R11: f000000000000000 R12: ffffc9000236fd30 R13: ffff8805c76bab80 R14: ffff8805c77ac800 R15: ffff88083fb12e10 FS: 00007fac8cbff040(0000) GS:ffff88083fd00000(0000) knlGS:0000000000000= 000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fffa6783ff8 CR3: 00000005c6e2b003 CR4: 00000000000606e0 Call Trace: xfs_ialloc+0x383/0x570 xfs_dir_ialloc+0x6a/0x2a0 xfs_create+0x412/0x670 xfs_generic_create+0x1f7/0x2c0 ? capable_wrt_inode_uidgid+0x3f/0x50 vfs_mkdir+0xfb/0x1b0 SyS_mkdir+0xcf/0xf0 do_syscall_64+0x73/0x1a0 entry_SYSCALL_64_after_hwframe+0x42/0xb7
Extracting the inode number we crashed on from an event trace and looking at it with xfs_db:
xfs_db> inode 184452204xfs_db> p
core.magic = 0x494e
core.mode = 0100644
core.version = 2
core.format = 2 (extents)
core.nlinkv2 = 1
core.onlink = 0
.....
Confirms that it is not a free inode on disk. xfs_repair also trips over this inode:
.....
zero length extent (off = 0, fsbno = 0) in ino 184452204 correcting nextents for inode 184452204
bad attribute fork in inode 184452204, would clear attr fork bad nblocks 1 for inode 184452204, would reset to 0 bad anextents 1 for inode 184452204, would reset to 0 imap claims in-use inode 184452204 is free, would correct imap would have cleared inode 184452204
.....
disconnected inode 184452204, would move to lost+found
And so we have a situation where the directory structure and the inobt thinks the inode is free, but the inode on disk thinks it is still in use. Where this corruption came from is not possible to diagnose, but we can detect it and prevent the kernel from oopsing on lookup. The reproducer now results in:
$ sudo mkdir /mnt/scratch/{0,1,2,3,4,5}{0,1,2,3,4,5}
mkdir: cannot create directory =E2=80=98/mnt/scratch/00=E2=80=99: File ex=
ists
mkdir: cannot create directory =E2=80=98/mnt/scratch/01=E2=80=99: File ex=
ists
mkdir: cannot create directory =E2=80=98/mnt/scratch/03=E2=80=99: Structu=
re needs cleaning
mkdir: cannot create directory =E2=80=98/mnt/scratch/04=E2=80=99: Input/o=
utput error
mkdir: cannot create directory =E2=80=98/mnt/scratch/05=E2=80=99: Input/o=
utput error
....And this corruption shutdown:
[ 54.843517] XFS (loop0): Corruption detected! Free inode 0xafe846c not= marked free on disk [ 54.845885] XFS (loop0): Internal error xfs_trans_cancel at line 1023 = of file fs/xfs/xfs_trans.c. Caller xfs_create+0x425/0x670 [ 54.848994] CPU: 10 PID: 3541 Comm: mkdir Not tainted 4.16.0-rc5-dgc #= 443 [ 54.850753] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIO= S 1.10.2-1 04/01/2014 [ 54.852859] Call Trace: [ 54.853531] dump_stack+0x85/0xc5 [ 54.854385] xfs_trans_cancel+0x197/0x1c0 [ 54.855421] xfs_create+0x425/0x670 [ 54.856314] xfs_generic_create+0x1f7/0x2c0 [ 54.857390] ? capable_wrt_inode_uidgid+0x3f/0x50 [ 54.858586] vfs_mkdir+0xfb/0x1b0 [ 54.859458] SyS_mkdir+0xcf/0xf0 [ 54.860254] do_syscall_64+0x73/0x1a0 [ 54.861193] entry_SYSCALL_64_after_hwframe+0x42/0xb7 [ 54.862492] RIP: 0033:0x7fb73bddf547 [ 54.863358] RSP: 002b:00007ffdaa553338 EFLAGS: 00000246 ORIG_RAX: 0000= 000000000053 [ 54.865133] RAX: ffffffffffffffda RBX: 00007ffdaa55449a RCX: 00007fb73= bddf547 [ 54.866766] RDX: 0000000000000001 RSI: 00000000000001ff RDI: 00007ffda= a55449a [ 54.868432] RBP: 00007ffdaa55449a R08: 00000000000001ff R09: 00005623a= 8670dd0 [ 54.870110] R10: 00007fb73be72d5b R11: 0000000000000246 R12: 000000000= 00001ff [ 54.871752] R13: 00007ffdaa5534b0 R14: 0000000000000000 R15: 00007ffda= a553500 [ 54.873429] XFS (loop0): xfs_do_force_shutdown(0x8) called from line 1= 024 of file fs/xfs/xfs_trans.c. Return address = ffffffff814cd050 [ 54.882790] XFS (loop0): Corruption of in-memory data detected. Shutt= ing down filesystem [ 54.884597] XFS (loop0): Please umount the filesystem and rectify the =
problem(s)
Note that this crash is only possible on v4 filesystemsi or v5 filesystems mounted with the ikeep mount option. For all other V5 filesystems, this problem cannot occur because we don't read inodes we are allocating from disk - we simply overwrite them with the new inode information.
--- fs/xfs/xfs_icache.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
fs/xfs/xfs_icache.c +22 -1
@@ -298,7 +298,28 @@ xfs_iget_cache_miss(trace_xfs_iget_miss (ip); -if ((ip->i_d.di_mode ==0 ) && !(flags &XFS_IGET_CREATE )) { + +/* +* If we are allocating a new inode, then check what was returned is +* actually a free, empty inode. If we are not allocating an inode, +* the check we didn't find a free inode. +*/ +if (flags &XFS_IGET_CREATE ) { +if (ip->i_d.di_mode !=0 ) { +xfs_warn (mp, +"Corruption detected! Free inode 0x%llx not marked free on disk" , + ino); + error = -EFSCORRUPTED ; + goto out_destroy; + } +if (ip->i_d.di_nblocks !=0 ) { +xfs_warn (mp, +"Corruption detected! Free inode 0x%llx has blocks allocated!" , + ino); + error = -EFSCORRUPTED ; + goto out_destroy; + } + }else if (ip->i_d.di_mode ==0 ) { error = -ENOENT ; goto out_destroy; }
Greg Kroah-Hartman
maintainerPATCH 11/15 xfs: validate cached inodes are free when allocated
In reply to Greg Kroah-HartmanFrom: Dave Chinner <[email protected]>
commit afca6c5b2595fc44383919fba740c194b0b76aff upstream
A recent fuzzed filesystem image cached random dcache corruption when the reproducer was run. This often showed up as panics in lookup_slow() on a null inode->i_ops pointer when doing pathwalks.
BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 .... Call Trace: lookup_slow+0x44/0x60 walk_component+0x3dd/0x9f0 link_path_walk+0x4a7/0x830 path_lookupat+0xc1/0x470 filename_lookup+0x129/0x270 user_path_at_empty+0x36/0x40 path_listxattr+0x98/0x110 SyS_listxattr+0x13/0x20 do_syscall_64+0xf5/0x280 entry_SYSCALL_64_after_hwframe+0x42/0xb7
but had many different failure modes including deadlocks trying to lock the inode that was just allocated or KASAN reports of use-after-free violations.
The cause of the problem was a corrupt INOBT on a v4 fs where the root inode was marked as free in the inobt record. Hence when we allocated an inode, it chose the root inode to allocate, found it in the cache and re-initialised it.
We recently fixed a similar inode allocation issue caused by inobt record corruption problem in xfs_iget_cache_miss() in commit ee457001ed6c ("xfs: catch inode allocation state mismatch corruption"). This change adds similar checks to the cache-hit path to catch it, and turns the reproducer into a corruption shutdown situation.
--- fs/xfs/xfs_icache.c | 73 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 25 deletions(-)
fs/xfs/xfs_icache.c +48 -25
@@ -135,6 +135,46 @@ xfs_inode_free( }/* +* If we are allocating a new inode, then check what was returned is +* actually a free, empty inode. If we are not allocating an inode, +* then check we didn't find a free inode. +* +* Returns: +* 0 if the inode free state matches the lookup context +* -ENOENT if the inode is free and we are not allocating +* -EFSCORRUPTED if there is any state mismatch at all +*/ +static int +xfs_iget_check_free_state ( +struct xfs_inode *ip, +int flags) +{ +if (flags &XFS_IGET_CREATE ) { +/* should be a free inode */ +if (ip->i_d.di_mode !=0 ) { +xfs_warn (ip->i_mount, +"Corruption detected! Free inode 0x%llx not marked free! (mode 0x%x)" , + ip->i_ino, ip->i_d.di_mode); +return -EFSCORRUPTED ; + } + +if (ip->i_d.di_nblocks !=0 ) { +xfs_warn (ip->i_mount, +"Corruption detected! Free inode 0x%llx has blocks allocated!" , + ip->i_ino); +return -EFSCORRUPTED ; + } +return 0 ; + } + +/* should be an allocated inode */ +if (ip->i_d.di_mode ==0 ) +return -ENOENT ; + +return 0 ; +} + +/* * Check the validity of the inode we just found it the cache */ static int
@@ -183,12 +223,12 @@ xfs_iget_cache_hit( }/* -* If lookup is racing with unlink return an error immediately. +* Check the inode free state is valid. This also detects lookup +* racing with unlinks. */ -if (ip->i_d.di_mode ==0 && !(flags &XFS_IGET_CREATE )) { - error = -ENOENT ; + error =xfs_iget_check_free_state (ip, flags); +if (error) goto out_error; - }/* * If IRECLAIMABLE is set, we've torn down the VFS inode already.
@@ -300,29 +340,12 @@ xfs_iget_cache_miss(/* -* If we are allocating a new inode, then check what was returned is -* actually a free, empty inode. If we are not allocating an inode, -* the check we didn't find a free inode. +* Check the inode free state is valid. This also detects lookup +* racing with unlinks. */ -if (flags &XFS_IGET_CREATE ) { -if (ip->i_d.di_mode !=0 ) { -xfs_warn (mp, -"Corruption detected! Free inode 0x%llx not marked free on disk" , - ino); - error = -EFSCORRUPTED ; - goto out_destroy; - } -if (ip->i_d.di_nblocks !=0 ) { -xfs_warn (mp, -"Corruption detected! Free inode 0x%llx has blocks allocated!" , - ino); - error = -EFSCORRUPTED ; - goto out_destroy; - } - }else if (ip->i_d.di_mode ==0 ) { - error = -ENOENT ; + error =xfs_iget_check_free_state (ip, flags); +if (error) goto out_destroy; - }/* * Preload the radix tree so we can insert safely under the
Greg Kroah-Hartman
maintainerPATCH 12/15 powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit 29daf869cbab69088fe1755d9dd224e99ba78b56 upstream.
The kernel expects pte_young() to work regardless of CONFIG_SWAP.
Make sure a minor fault is taken to set _PAGE_ACCESSED when it is not already set, regardless of the selection of CONFIG_SWAP.
This adds at least 3 instructions to the TLB miss exception handlers fast path. Following patch will reduce this overhead.
Also update the rotation instruction to the correct number of bits to reflect all changes done to _PAGE_ACCESSED over time.
--- arch/powerpc/kernel/head_8xx.S | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
arch/powerpc/kernel/head_8xx.S +2 -6
@@ -361,11 +361,9 @@ InstructionTLBMiss: /* Load the MI_TWC with the attributes for this "segment." */ MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ -#ifdef CONFIG_SWAP - rlwinm r11, r10, 32-5, _PAGE_PRESENT + rlwinm r11, r10, 32-11, _PAGE_PRESENT and r11, r11, r10 rlwimi r10, r11, 0, _PAGE_PRESENT -#endif li r11, RPN_PATTERN /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 20-23 and 28 must be clear.
@@ -436,11 +434,9 @@ DataStoreTLBMiss: * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); * r10 = (r10 & ~PRESENT) | r11; */ -#ifdef CONFIG_SWAP - rlwinm r11, r10, 32-5, _PAGE_PRESENT + rlwinm r11, r10, 32-11, _PAGE_PRESENT and r11, r11, r10 rlwimi r10, r11, 0, _PAGE_PRESENT -#endif /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 22 and 28 must be clear. * Software indicator bits 24, 25, 26, and 27 must be
Greg Kroah-Hartman
maintainerPATCH 13/15 Input: sunkbd - avoid use-after-free in teardown paths
In reply to Greg Kroah-HartmanFrom: Dmitry Torokhov <[email protected]>
commit 77e70d351db7de07a46ac49b87a6c3c7a60fca7e upstream.
We need to make sure we cancel the reinit work before we tear down the driver structures.
--- drivers/input/keyboard/sunkbd.c | 41 ++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-)
drivers/input/keyboard/sunkbd.c +33 -8
@@ -115,7 +115,8 @@ static irqreturn_t sunkbd_interrupt(struswitch (data) {case SUNKBD_RET_RESET : -schedule_work (&sunkbd->tq); +if (sunkbd->enabled) +schedule_work (&sunkbd->tq); sunkbd->reset =-1 ;break ;
@@ -216,16 +217,12 @@ static int sunkbd_initialize(struct sunk }/* -* sunkbd_reinit() sets leds and beeps to a state the computer remembers they -* were in. +* sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers +* they were in. */ -static void sunkbd_reinit (struct work_struct *work) +static void sunkbd_set_leds_beeps (struct sunkbd *sunkbd) { - struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); - -wait_event_interruptible_timeout (sunkbd->wait, sunkbd->reset >=0 ,HZ ); -serio_write (sunkbd->serio,SUNKBD_CMD_SETLED ); serio_write(sunkbd->serio, (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) |
@@ -238,11 +235,39 @@ static void sunkbd_reinit(struct work_st SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); } + +/* +* sunkbd_reinit() wait for the keyboard reset to complete and restores state +* of leds and beeps. +*/ + +static void sunkbd_reinit (struct work_struct *work) +{ + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); + +/* +* It is OK that we check sunkbd->enabled without pausing serio, +* as we only want to catch true->false transition that will +* happen once and we will be woken up for it. +*/ +wait_event_interruptible_timeout (sunkbd->wait, + sunkbd->reset >=0 || !sunkbd->enabled, +HZ ); + +if (sunkbd->reset >=0 && sunkbd->enabled) +sunkbd_set_leds_beeps (sunkbd); +} +static void sunkbd_enable (struct sunkbd *sunkbd,bool enable) {serio_pause_rx (sunkbd->serio); sunkbd->enabled = enable;serio_continue_rx (sunkbd->serio); + +if (!enable) { +wake_up_interruptible (&sunkbd->wait); +cancel_work_sync (&sunkbd->tq); + } }/*
Greg Kroah-Hartman
maintainerPATCH 14/15 mac80211: always wind down STA state
In reply to Greg Kroah-HartmanFrom: Johannes Berg <[email protected]>
commit dcd479e10a0510522a5d88b29b8f79ea3467d501 upstream.
When (for example) an IBSS station is pre-moved to AUTHORIZED before it's inserted, and then the insertion fails, we don't clean up the fast RX/TX states that might already have been created, since we don't go through all the state transitions again on the way down.
Do that, if it hasn't been done already, when the station is freed. I considered only freeing the fast TX/RX state there, but we might add more state so it's more robust to wind down the state properly.
Note that we warn if the station was ever inserted, it should have been properly cleaned up in that case, and the driver will probably not like things happening out of order.
--- net/mac80211/sta_info.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
net/mac80211/sta_info.c +18 -0
@@ -242,6 +242,24 @@ struct sta_info *sta_info_get_by_idx(str*/ void sta_info_free (struct ieee80211_local *local,struct sta_info *sta) { +/* +* If we had used sta_info_pre_move_state() then we might not +* have gone through the state transitions down again, so do +* it here now (and warn if it's inserted). +* +* This will clear state such as fast TX/RX that may have been +* allocated during state transitions. +*/ +while (sta->sta_state >IEEE80211_STA_NONE ) { +int ret; + +WARN_ON_ONCE (test_sta_flag (sta,WLAN_STA_INSERTED )); + + ret =sta_info_move_state (sta, sta->sta_state -1 ); +if (WARN_ONCE (ret,"sta_info_move_state() returned %d\n" , ret)) +break ; + } +if (sta->rate_ctrl)rate_control_free_sta (sta);
Greg Kroah-Hartman
maintainerPATCH 15/15 KVM: x86: clflushopt should be treated as a no-op by emulation
In reply to Greg Kroah-HartmanFrom: David Edmondson <[email protected]>
commit 51b958e5aeb1e18c00332e0b37c5d4e95a3eff84 upstream.
The instruction emulator ignores clflush instructions, yet fails to support clflushopt. Treat both similarly.
Message-Id: <[email protected]>
--- arch/x86/kvm/emulate.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/x86/kvm/emulate.c +7 -1
@@ -3922,6 +3922,12 @@ static int em_clflush(struct x86_emulatereturn X86EMUL_CONTINUE ; } +static int em_clflushopt (struct x86_emulate_ctxt *ctxt) +{ +/* emulating clflushopt regardless of cpuid */ +return X86EMUL_CONTINUE ; +} +static int em_movsxd (struct x86_emulate_ctxt *ctxt) { ctxt->dst.val = (s32 ) ctxt->src.val;
@@ -4411,7 +4417,7 @@ static const struct opcode group11[] = { };static const struct gprefix pfx_0f_ae_7 = { -I (SrcMem | ByteOp, em_clflush),N ,N ,N , +I (SrcMem | ByteOp, em_clflush),I (SrcMem | ByteOp, em_clflushopt),N ,N , };static const struct group_dual group15 = { {
Hi!
Quoted 7 lines
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-4.4.y
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.245-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v4.4:
6 builds: 6 pass, 0 fail
12 boots: 12 pass, 0 fail
25 tests: 25 pass, 0 failLinux version: 4.4.245-rc1-g11095ab90e22
Boards tested: tegra124-jetson-tk1, tegra20-ventana,
tegra30-cardhu-a04
Jon
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.245-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
Build results:
total: 165 pass: 164 fail: 1 Failed builds: powerpc:ppc64e_defconfig Qemu test results: total: 328 pass: 323 fail: 5 Failed tests: ppc64:ppce500:corenet64_smp_defconfig:e5500:initrd ppc64:ppce500:corenet64_smp_defconfig:e5500:nvme:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:sdhci:mmc:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:scsi[53C895A]:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:sata-sii3112:rootfs
Failure in all cases is:
In file included from arch/powerpc/kernel/ppc_ksyms.c:10:0:arch/powerpc/include/asm/book3s/64/kup-radix.h:11:29: error: redefinition of ‘allow_user_access’
static __always_inline void allow_user_access(void __user *to, const void __user *from,
^~~~~~~~~~~~~~~~~
In file included from arch/powerpc/include/asm/uaccess.h:12:0,
from arch/powerpc/kernel/ppc_ksyms.c:8:arch/powerpc/include/asm/kup.h:12:20: note: previous definition of ‘allow_user_access’ was here
static inline void allow_user_access(void __user *to, const void __user *from,
^~~~~~~~~~~~~~~~~
In file included from arch/powerpc/kernel/ppc_ksyms.c:10:0:
arch/powerpc/include/asm/book3s/64/kup-radix.h:16:20: error: redefinition of ‘prevent_user_access’
static inline void prevent_user_access(void __user *to, const void __user *from,
^~~~~~~~~~~~~~~~~~~In file included from arch/powerpc/include/asm/uaccess.h:12:0,
from arch/powerpc/kernel/ppc_ksyms.c:8:arch/powerpc/include/asm/kup.h:14:20: note: previous definition of ‘prevent_user_access’ was here
static inline void prevent_user_access(void __user *to, const void __user *from,
^~~~~~~~~~~~~~~~~~~
Guenter
Greg Kroah-Hartman
maintainerQuoted 37 lines · Guenter Roeck
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
Build results:
total: 165 pass: 164 fail: 1 Failed builds: powerpc:ppc64e_defconfig Qemu test results: total: 328 pass: 323 fail: 5 Failed tests: ppc64:ppce500:corenet64_smp_defconfig:e5500:initrd ppc64:ppce500:corenet64_smp_defconfig:e5500:nvme:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:sdhci:mmc:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:scsi[53C895A]:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:sata-sii3112:rootfsFailure in all cases is:
In file included from
arch/powerpc/kernel/ppc_ksyms.c:10:0:arch/powerpc/include/asm/book3s/64/kup-radix.h:11:29: error: redefinition of ‘allow_user_access’
static__always_inlinevoid allow_user_access(void__user*to, const void__user*from,^~~~~~~~~~~~~~~~~In file included from
arch/powerpc/include/asm/uaccess.h:12:0,
fromarch/powerpc/kernel/ppc_ksyms.c:8:arch/powerpc/include/asm/kup.h:12:20: note: previous definition of ‘allow_user_access’ was here
static inline void allow_user_access(void__user*to, const void__user*from,^~~~~~~~~~~~~~~~~ In file included from arch/powerpc/kernel/ppc_ksyms.c:10:0: arch/powerpc/include/asm/book3s/64/kup-radix.h:16:20: error: redefinition of ‘prevent_user_access’ static inline void prevent_user_access(void __user *to, const void __user *from, ^~~~~~~~~~~~~~~~~~~
Quoted 7 lines
In file included from
arch/powerpc/include/asm/uaccess.h:12:0,
fromarch/powerpc/kernel/ppc_ksyms.c:8:arch/powerpc/include/asm/kup.h:14:20: note: previous definition of ‘prevent_user_access’ was here
static inline void prevent_user_access(void__user*to, const void__user*from,^~~~~~~~~~~~~~~~~~~Tested-by Guenter Roeck <[email protected]>
Thanks for testing these.
Daniel, looks like your patches broke some configurations on powerpc as shown above. Care to send a fix-up patch for these?
thanks,
greg k-h
Hi,
Quoted 34 lines
Quoted 34 lines
Build results:
total: 165 pass: 164 fail: 1 Failed builds: powerpc:ppc64e_defconfig Qemu test results: total: 328 pass: 323 fail: 5 Failed tests: ppc64:ppce500:corenet64_smp_defconfig:e5500:initrd ppc64:ppce500:corenet64_smp_defconfig:e5500:nvme:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:sdhci:mmc:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:scsi[53C895A]:rootfs ppc64:ppce500:corenet64_smp_defconfig:e5500:sata-sii3112:rootfsFailure in all cases is:
In file included from
arch/powerpc/kernel/ppc_ksyms.c:10:0:arch/powerpc/include/asm/book3s/64/kup-radix.h:11:29: error: redefinition of ‘allow_user_access’
static__always_inlinevoid allow_user_access(void__user*to, const void__user*from,^~~~~~~~~~~~~~~~~In file included from
arch/powerpc/include/asm/uaccess.h:12:0,
fromarch/powerpc/kernel/ppc_ksyms.c:8:arch/powerpc/include/asm/kup.h:12:20: note: previous definition of ‘allow_user_access’ was here
static inline void allow_user_access(void__user*to, const void__user*from,^~~~~~~~~~~~~~~~~ In file included from arch/powerpc/kernel/ppc_ksyms.c:10:0: arch/powerpc/include/asm/book3s/64/kup-radix.h:16:20: error: redefinition of ‘prevent_user_access’ static inline void prevent_user_access(void __user *to, const void __user *from, ^~~~~~~~~~~~~~~~~~~In file included from
arch/powerpc/include/asm/uaccess.h:12:0,
fromarch/powerpc/kernel/ppc_ksyms.c:8:arch/powerpc/include/asm/kup.h:14:20: note: previous definition of ‘prevent_user_access’ was here
static inline void prevent_user_access(void__user*to, const void__user*from,^~~~~~~~~~~~~~~~~~~
Quoted 6 lines
Quoted 1 line
Tested-by Guenter Roeck <[email protected]>Thanks for testing these.
Daniel, looks like your patches broke some configurations on powerpc as shown above. Care to send a fix-up patch for these?
Will do. I tested ppc64e_defconfig but clearly that wasn't comprehensive enough.
Kind regards,
Daniel
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.4.245 release. There are 15 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 22 Nov 2020 10:45:32 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.245-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.4.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
Summary
------------------------------------------------------------------------
kernel: 4.4.245-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-4.4.y
git commit: 11095ab90e22ac875983239a445f6b4ad64b6e08
git describe: v4.4.244-16-g11095ab90e22
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-4.4.y/build/v4.4.244-16-g11095ab90e22
No regressions (compared to build v4.4.244)
No fixes (compared to build v4.4.244)
Ran 32775 total tests in the following environments and test suites.
Environments
--------------
- i386
- juno-r2 - arm64
- juno-r2-compat
- juno-r2-kasan
- qemu-arm64-clang
- qemu-arm64-kasan
- qemu-x86_64-clang
- qemu-x86_64-kasan
- qemu_arm
- qemu_arm64
- qemu_arm64-compat
- qemu_i386
- qemu_x86_64
- qemu_x86_64-compat
- x15 - arm
- x86_64
- x86-kasan
Test Suites
-----------
* build
* libhugetlbfs
* linux-log-parser
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-controllers-tests
* ltp-cpuhotplug-tests
* ltp-crypto-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-open-posix-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* network-basic-tests
* perf
* v4l2-compliance
* kvm-unit-tests
* ltp-tracing-tests
* install-android-platform-tools-r2600
Summary
------------------------------------------------------------------------
kernel: 4.4.245-rc1
git repo: https://git.linaro.org/lkft/arm64-stable-rc.git
git branch: 4.4.245-rc1-hikey-20201120-861
git commit: a395e149575bc8d8ec23a677f979301bfefd8862
git describe: 4.4.245-rc1-hikey-20201120-861
Test details: https://qa-reports.linaro.org/lkft/linaro-hikey-stable-rc-4.4-oe/build/4.4.245-rc1-hikey-20201120-861
No regressions (compared to build 4.4.244-rc1-hikey-20201117-859)
No fixes (compared to build 4.4.244-rc1-hikey-20201117-859)
Ran 1722 total tests in the following environments and test suites.
Environments
--------------
- hi6220-hikey - arm64
Test Suites
-----------
* build
* install-android-platform-tools-r2600
* libhugetlbfs
* linux-log-parser
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* perf
* spectre-meltdown-checker-test
* v4l2-compliance
Signature · 2 lines
Linaro LKFT https://lkft.linaro.org