Changes since v1 [1]: * fixup the ifence definition to use alternative_2 per recent AMD changes in tip/x86/pti (Tom) * drop 'nospec_ptr' (Linus, Mark) * rename 'nospec_array_ptr' to 'array_ptr' (Alexei) * rename 'nospec_barrier' to 'ifence' (Peter, Ingo) * clean up occasions of 'variable assignment in if()' (Sergei, Stephen) * make 'array_ptr' use a mask instead of an architectural ifence by default (Linus, Alexei) * provide a command line and compile-time opt-in to the ifence mechanism, if an architecture provides 'ifence_array_ptr'. * provide an optimized mask generation helper, 'array_ptr_mask', for x86 (Linus) * move 'get_user' hardening from '__range_not_ok' to '__uaccess_begin' (Linus) * drop "Thermal/int340x: prevent bounds-check..." since userspace does not have arbitrary control over the 'trip' index (Srinivas) * update the changelog of "net: mpls: prevent bounds-check..." and keep it in the series to continue the debate about Spectre hygiene patches. (Eric). * record a reviewed-by from Laurent on "[media] uvcvideo: prevent bounds-check..." * update the cover letter [1]: https://lwn.net/Articles/743376/ --- Quoting Mark's original RFC: "Recently, Google Project Zero discovered several classes of attack against speculative execution. One of these, known as variant-1, allows explicit bounds checks to be bypassed under speculation, providing an arbitrary read gadget. Further details can be found on the GPZ blog [2] and the Documentation patch in this series." This series incorporates Mark Rutland's latest ARM changes and adds the x86 specific implementation of 'ifence_array_ptr'. That ifence based approach is provided as an opt-in fallback, but the default mitigation, '__array_ptr', uses a 'mask' approach that removes conditional branches instructions, and otherwise aims to redirect speculation to use a NULL pointer rather than a user controlled value. The mask is generated by the following from Alexei, and Linus: mask = ~(long)(_i | (_s - 1 - _i)) >> (BITS_PER_LONG - 1); ...and Linus provided an optimized mask generation helper for x86: asm ("cmpq %1,%2; sbbq %0,%0;" :"=r" (mask) :"r"(sz),"r" (idx) :"cc"); The 'array_ptr' mechanism can be switched between 'mask' and 'ifence' via the spectre_v1={mask,ifence} command line option, and the compile-time default is set by selecting either CONFIG_SPECTRE1_MASK or CONFIG_SPECTRE1_IFENCE. The 'array_ptr' infrastructure is the primary focus this patch set. The individual patches that perform 'array_ptr' conversions are a point in time (i.e. earlier kernel, early analysis tooling, x86 only etc...) start at finding some of these gadgets. Another consideration for reviewing these patches is the 'hygiene' argument. When a patch refers to hygiene it is concerned with stopping speculation on an unconstrained or insufficiently constrained pointer value under userspace control. That by itself is not sufficient for attack (per current understanding) [3], but it is a necessary pre-condition. So 'hygiene' refers to cleaning up those suspect pointers regardless of whether they are usable as a gadget. These patches are also be available via the 'nospec-v2' git branch here: git://git.kernel.org/pub/scm/linux/kernel/git/djbw/linux nospec-v2 Note that the BPF fix for Spectre variant1 is merged in the bpf.git tree [4], and is not included in this branch. [2]: https://googleprojectzero.blogspot.co.uk/2018/01/reading-privileged-memory-with-side.html [3]: https://spectreattack.com/spectre.pdf [4]: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git/commit/?id=b2157399cc98 --- Dan Williams (16): x86: implement ifence() x86: implement ifence_array_ptr() and array_ptr_mask() asm-generic/barrier: mask speculative execution flows x86: introduce __uaccess_begin_nospec and ASM_IFENCE x86: use __uaccess_begin_nospec and ASM_IFENCE in get_user paths ipv6: prevent bounds-check bypass via speculative execution ipv4: prevent bounds-check bypass via speculative execution vfs, fdtable: prevent bounds-check bypass via speculative execution userns: prevent bounds-check bypass via speculative execution udf: prevent bounds-check bypass via speculative execution [media] uvcvideo: prevent bounds-check bypass via speculative execution carl9170: prevent bounds-check bypass via speculative execution p54: prevent bounds-check bypass via speculative execution qla2xxx: prevent bounds-check bypass via speculative execution cw1200: prevent bounds-check bypass via speculative execution net: mpls: prevent bounds-check bypass via speculative execution Mark Rutland (3): Documentation: document array_ptr arm64: implement ifence_array_ptr() arm: implement ifence_array_ptr() Documentation/speculation.txt | 142 ++++++++++++++++++++++++++++++ arch/arm/Kconfig | 1 arch/arm/include/asm/barrier.h | 24 +++++ arch/arm64/Kconfig | 1 arch/arm64/include/asm/barrier.h | 24 +++++ arch/x86/Kconfig | 3 + arch/x86/include/asm/barrier.h | 46 ++++++++++ arch/x86/include/asm/msr.h | 3 - arch/x86/include/asm/smap.h | 4 + arch/x86/include/asm/uaccess.h | 16 +++ arch/x86/include/asm/uaccess_32.h | 6 + arch/x86/include/asm/uaccess_64.h | 12 +-- arch/x86/lib/copy_user_64.S | 3 + arch/x86/lib/usercopy_32.c | 8 +- drivers/media/usb/uvc/uvc_v4l2.c | 9 +- drivers/net/wireless/ath/carl9170/main.c | 7 + drivers/net/wireless/intersil/p54/main.c | 9 +- drivers/net/wireless/st/cw1200/sta.c | 11 +- drivers/net/wireless/st/cw1200/wsm.h | 4 - drivers/scsi/qla2xxx/qla_mr.c | 17 ++-- fs/udf/misc.c | 40 +++++--- include/linux/fdtable.h | 7 + include/linux/nospec.h | 71 +++++++++++++++ kernel/Kconfig.nospec | 31 +++++++ kernel/Makefile | 1 kernel/nospec.c | 52 +++++++++++ kernel/user_namespace.c | 11 +- lib/Kconfig | 3 + net/ipv4/raw.c | 10 +- net/ipv6/raw.c | 10 +- net/mpls/af_mpls.c | 12 +-- 31 files changed, 521 insertions(+), 77 deletions(-) create mode 100644 Documentation/speculation.txt create mode 100644 include/linux/nospec.h create mode 100644 kernel/Kconfig.nospec create mode 100644 kernel/nospec.c