diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-27 14:14:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-27 14:14:25 -0400 |
commit | 19b522dbad0d0c35d0741a74aef70ce6fe2d6fb4 (patch) | |
tree | a842aba427dfb651790d4e06b7582c42ce8d8879 | |
parent | 7b87308e710858e95729b9e33c8b79e2a1564d37 (diff) | |
parent | 3789c122d0a016b947ce5c05d3f1fbafa5db8f26 (diff) |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon:
"Nothing too bad, but the spectre updates to smatch identified a few
places that may need sanitising so we've got those covered.
Details:
- Close some potential spectre-v1 vulnerabilities found by smatch
- Add missing list sentinel for CPUs that don't require KPTI
- Removal of unused 'addr' parameter for I/D cache coherency
- Removal of redundant set_fs(KERNEL_DS) calls in ptrace
- Fix single-stepping state machine handling in response to kernel
traps
- Clang support for 128-bit integers
- Avoid instrumenting our out-of-line atomics in preparation for
enabling LSE atomics by default in 4.18"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: avoid instrumenting atomic_ll_sc.o
KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_mmio_read_apr()
KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_get_irq()
arm64: fix possible spectre-v1 in ptrace_hbp_get_event()
arm64: support __int128 with clang
arm64: only advance singlestep for user instruction traps
arm64/kernel: rename module_emit_adrp_veneer->module_emit_veneer_for_adrp
arm64: ptrace: remove addr_limit manipulation
arm64: mm: drop addr parameter from sync icache and dcache
arm64: add sentinel to kpti_safe_list
-rw-r--r-- | arch/arm64/Makefile | 4 | ||||
-rw-r--r-- | arch/arm64/include/asm/module.h | 2 | ||||
-rw-r--r-- | arch/arm64/include/asm/pgtable.h | 4 | ||||
-rw-r--r-- | arch/arm64/kernel/cpufeature.c | 1 | ||||
-rw-r--r-- | arch/arm64/kernel/module-plts.c | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/module.c | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/ptrace.c | 20 | ||||
-rw-r--r-- | arch/arm64/kernel/traps.c | 3 | ||||
-rw-r--r-- | arch/arm64/lib/Makefile | 4 | ||||
-rw-r--r-- | arch/arm64/mm/flush.c | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v2.c | 5 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic.c | 14 |
12 files changed, 42 insertions, 21 deletions
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 15402861bb59..87f7d2f9f17c 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile | |||
@@ -56,7 +56,11 @@ KBUILD_AFLAGS += $(lseinstr) $(brokengasinst) | |||
56 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) | 56 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) |
57 | KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) | 57 | KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) |
58 | 58 | ||
59 | ifeq ($(cc-name),clang) | ||
60 | KBUILD_CFLAGS += -DCONFIG_ARCH_SUPPORTS_INT128 | ||
61 | else | ||
59 | KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128) | 62 | KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128) |
63 | endif | ||
60 | 64 | ||
61 | ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) | 65 | ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) |
62 | KBUILD_CPPFLAGS += -mbig-endian | 66 | KBUILD_CPPFLAGS += -mbig-endian |
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index b6dbbe3123a9..97d0ef12e2ff 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h | |||
@@ -39,7 +39,7 @@ struct mod_arch_specific { | |||
39 | u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela *rela, | 39 | u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela *rela, |
40 | Elf64_Sym *sym); | 40 | Elf64_Sym *sym); |
41 | 41 | ||
42 | u64 module_emit_adrp_veneer(struct module *mod, void *loc, u64 val); | 42 | u64 module_emit_veneer_for_adrp(struct module *mod, void *loc, u64 val); |
43 | 43 | ||
44 | #ifdef CONFIG_RANDOMIZE_BASE | 44 | #ifdef CONFIG_RANDOMIZE_BASE |
45 | extern u64 module_alloc_base; | 45 | extern u64 module_alloc_base; |
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 7e2c27e63cd8..7c4c8f318ba9 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -230,7 +230,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte) | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); | 233 | extern void __sync_icache_dcache(pte_t pteval); |
234 | 234 | ||
235 | /* | 235 | /* |
236 | * PTE bits configuration in the presence of hardware Dirty Bit Management | 236 | * PTE bits configuration in the presence of hardware Dirty Bit Management |
@@ -253,7 +253,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
253 | pte_t old_pte; | 253 | pte_t old_pte; |
254 | 254 | ||
255 | if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte)) | 255 | if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte)) |
256 | __sync_icache_dcache(pte, addr); | 256 | __sync_icache_dcache(pte); |
257 | 257 | ||
258 | /* | 258 | /* |
259 | * If the existing pte is valid, check for potential race with | 259 | * If the existing pte is valid, check for potential race with |
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 536d572e5596..9d1b06d67c53 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
@@ -868,6 +868,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, | |||
868 | static const struct midr_range kpti_safe_list[] = { | 868 | static const struct midr_range kpti_safe_list[] = { |
869 | MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), | 869 | MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), |
870 | MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), | 870 | MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), |
871 | { /* sentinel */ } | ||
871 | }; | 872 | }; |
872 | char const *str = "command line option"; | 873 | char const *str = "command line option"; |
873 | 874 | ||
diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c index fa3637284a3d..f0690c2ca3e0 100644 --- a/arch/arm64/kernel/module-plts.c +++ b/arch/arm64/kernel/module-plts.c | |||
@@ -43,7 +43,7 @@ u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela *rela, | |||
43 | } | 43 | } |
44 | 44 | ||
45 | #ifdef CONFIG_ARM64_ERRATUM_843419 | 45 | #ifdef CONFIG_ARM64_ERRATUM_843419 |
46 | u64 module_emit_adrp_veneer(struct module *mod, void *loc, u64 val) | 46 | u64 module_emit_veneer_for_adrp(struct module *mod, void *loc, u64 val) |
47 | { | 47 | { |
48 | struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : | 48 | struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : |
49 | &mod->arch.init; | 49 | &mod->arch.init; |
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 719fde8dcc19..155fd91e78f4 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c | |||
@@ -215,7 +215,7 @@ static int reloc_insn_adrp(struct module *mod, __le32 *place, u64 val) | |||
215 | insn &= ~BIT(31); | 215 | insn &= ~BIT(31); |
216 | } else { | 216 | } else { |
217 | /* out of range for ADR -> emit a veneer */ | 217 | /* out of range for ADR -> emit a veneer */ |
218 | val = module_emit_adrp_veneer(mod, place, val & ~0xfff); | 218 | val = module_emit_veneer_for_adrp(mod, place, val & ~0xfff); |
219 | if (!val) | 219 | if (!val) |
220 | return -ENOEXEC; | 220 | return -ENOEXEC; |
221 | insn = aarch64_insn_gen_branch_imm((u64)place, val, | 221 | insn = aarch64_insn_gen_branch_imm((u64)place, val, |
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 71d99af24ef2..7ff81fed46e1 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/sched/signal.h> | 25 | #include <linux/sched/signal.h> |
26 | #include <linux/sched/task_stack.h> | 26 | #include <linux/sched/task_stack.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/nospec.h> | ||
28 | #include <linux/smp.h> | 29 | #include <linux/smp.h> |
29 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
30 | #include <linux/user.h> | 31 | #include <linux/user.h> |
@@ -249,15 +250,20 @@ static struct perf_event *ptrace_hbp_get_event(unsigned int note_type, | |||
249 | 250 | ||
250 | switch (note_type) { | 251 | switch (note_type) { |
251 | case NT_ARM_HW_BREAK: | 252 | case NT_ARM_HW_BREAK: |
252 | if (idx < ARM_MAX_BRP) | 253 | if (idx >= ARM_MAX_BRP) |
253 | bp = tsk->thread.debug.hbp_break[idx]; | 254 | goto out; |
255 | idx = array_index_nospec(idx, ARM_MAX_BRP); | ||
256 | bp = tsk->thread.debug.hbp_break[idx]; | ||
254 | break; | 257 | break; |
255 | case NT_ARM_HW_WATCH: | 258 | case NT_ARM_HW_WATCH: |
256 | if (idx < ARM_MAX_WRP) | 259 | if (idx >= ARM_MAX_WRP) |
257 | bp = tsk->thread.debug.hbp_watch[idx]; | 260 | goto out; |
261 | idx = array_index_nospec(idx, ARM_MAX_WRP); | ||
262 | bp = tsk->thread.debug.hbp_watch[idx]; | ||
258 | break; | 263 | break; |
259 | } | 264 | } |
260 | 265 | ||
266 | out: | ||
261 | return bp; | 267 | return bp; |
262 | } | 268 | } |
263 | 269 | ||
@@ -1458,9 +1464,7 @@ static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, | |||
1458 | { | 1464 | { |
1459 | int ret; | 1465 | int ret; |
1460 | u32 kdata; | 1466 | u32 kdata; |
1461 | mm_segment_t old_fs = get_fs(); | ||
1462 | 1467 | ||
1463 | set_fs(KERNEL_DS); | ||
1464 | /* Watchpoint */ | 1468 | /* Watchpoint */ |
1465 | if (num < 0) { | 1469 | if (num < 0) { |
1466 | ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); | 1470 | ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); |
@@ -1471,7 +1475,6 @@ static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, | |||
1471 | } else { | 1475 | } else { |
1472 | ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); | 1476 | ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); |
1473 | } | 1477 | } |
1474 | set_fs(old_fs); | ||
1475 | 1478 | ||
1476 | if (!ret) | 1479 | if (!ret) |
1477 | ret = put_user(kdata, data); | 1480 | ret = put_user(kdata, data); |
@@ -1484,7 +1487,6 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, | |||
1484 | { | 1487 | { |
1485 | int ret; | 1488 | int ret; |
1486 | u32 kdata = 0; | 1489 | u32 kdata = 0; |
1487 | mm_segment_t old_fs = get_fs(); | ||
1488 | 1490 | ||
1489 | if (num == 0) | 1491 | if (num == 0) |
1490 | return 0; | 1492 | return 0; |
@@ -1493,12 +1495,10 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, | |||
1493 | if (ret) | 1495 | if (ret) |
1494 | return ret; | 1496 | return ret; |
1495 | 1497 | ||
1496 | set_fs(KERNEL_DS); | ||
1497 | if (num < 0) | 1498 | if (num < 0) |
1498 | ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); | 1499 | ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); |
1499 | else | 1500 | else |
1500 | ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); | 1501 | ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); |
1501 | set_fs(old_fs); | ||
1502 | 1502 | ||
1503 | return ret; | 1503 | return ret; |
1504 | } | 1504 | } |
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 1cb2749a72bf..8bbdc17e49df 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
@@ -277,7 +277,8 @@ void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size) | |||
277 | * If we were single stepping, we want to get the step exception after | 277 | * If we were single stepping, we want to get the step exception after |
278 | * we return from the trap. | 278 | * we return from the trap. |
279 | */ | 279 | */ |
280 | user_fastforward_single_step(current); | 280 | if (user_mode(regs)) |
281 | user_fastforward_single_step(current); | ||
281 | } | 282 | } |
282 | 283 | ||
283 | static LIST_HEAD(undef_hook); | 284 | static LIST_HEAD(undef_hook); |
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 0ead8a1d1679..137710f4dac3 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile | |||
@@ -19,5 +19,9 @@ CFLAGS_atomic_ll_sc.o := -fcall-used-x0 -ffixed-x1 -ffixed-x2 \ | |||
19 | -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15 \ | 19 | -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15 \ |
20 | -fcall-saved-x18 -fomit-frame-pointer | 20 | -fcall-saved-x18 -fomit-frame-pointer |
21 | CFLAGS_REMOVE_atomic_ll_sc.o := -pg | 21 | CFLAGS_REMOVE_atomic_ll_sc.o := -pg |
22 | GCOV_PROFILE_atomic_ll_sc.o := n | ||
23 | KASAN_SANITIZE_atomic_ll_sc.o := n | ||
24 | KCOV_INSTRUMENT_atomic_ll_sc.o := n | ||
25 | UBSAN_SANITIZE_atomic_ll_sc.o := n | ||
22 | 26 | ||
23 | lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o | 27 | lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o |
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c index e36ed5087b5c..1059884f9a6f 100644 --- a/arch/arm64/mm/flush.c +++ b/arch/arm64/mm/flush.c | |||
@@ -58,7 +58,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | |||
58 | flush_ptrace_access(vma, page, uaddr, dst, len); | 58 | flush_ptrace_access(vma, page, uaddr, dst, len); |
59 | } | 59 | } |
60 | 60 | ||
61 | void __sync_icache_dcache(pte_t pte, unsigned long addr) | 61 | void __sync_icache_dcache(pte_t pte) |
62 | { | 62 | { |
63 | struct page *page = pte_page(pte); | 63 | struct page *page = pte_page(pte); |
64 | 64 | ||
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index e21e2f49b005..ffc587bf4742 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/irqchip/arm-gic.h> | 14 | #include <linux/irqchip/arm-gic.h> |
15 | #include <linux/kvm.h> | 15 | #include <linux/kvm.h> |
16 | #include <linux/kvm_host.h> | 16 | #include <linux/kvm_host.h> |
17 | #include <linux/nospec.h> | ||
18 | |||
17 | #include <kvm/iodev.h> | 19 | #include <kvm/iodev.h> |
18 | #include <kvm/arm_vgic.h> | 20 | #include <kvm/arm_vgic.h> |
19 | 21 | ||
@@ -324,6 +326,9 @@ static unsigned long vgic_mmio_read_apr(struct kvm_vcpu *vcpu, | |||
324 | 326 | ||
325 | if (n > vgic_v3_max_apr_idx(vcpu)) | 327 | if (n > vgic_v3_max_apr_idx(vcpu)) |
326 | return 0; | 328 | return 0; |
329 | |||
330 | n = array_index_nospec(n, 4); | ||
331 | |||
327 | /* GICv3 only uses ICH_AP1Rn for memory mapped (GICv2) guests */ | 332 | /* GICv3 only uses ICH_AP1Rn for memory mapped (GICv2) guests */ |
328 | return vgicv3->vgic_ap1r[n]; | 333 | return vgicv3->vgic_ap1r[n]; |
329 | } | 334 | } |
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index e74baec76361..bd125563b15b 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c | |||
@@ -14,11 +14,13 @@ | |||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/irq.h> | ||
17 | #include <linux/kvm.h> | 19 | #include <linux/kvm.h> |
18 | #include <linux/kvm_host.h> | 20 | #include <linux/kvm_host.h> |
19 | #include <linux/list_sort.h> | 21 | #include <linux/list_sort.h> |
20 | #include <linux/interrupt.h> | 22 | #include <linux/nospec.h> |
21 | #include <linux/irq.h> | 23 | |
22 | #include <asm/kvm_hyp.h> | 24 | #include <asm/kvm_hyp.h> |
23 | 25 | ||
24 | #include "vgic.h" | 26 | #include "vgic.h" |
@@ -101,12 +103,16 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu, | |||
101 | u32 intid) | 103 | u32 intid) |
102 | { | 104 | { |
103 | /* SGIs and PPIs */ | 105 | /* SGIs and PPIs */ |
104 | if (intid <= VGIC_MAX_PRIVATE) | 106 | if (intid <= VGIC_MAX_PRIVATE) { |
107 | intid = array_index_nospec(intid, VGIC_MAX_PRIVATE); | ||
105 | return &vcpu->arch.vgic_cpu.private_irqs[intid]; | 108 | return &vcpu->arch.vgic_cpu.private_irqs[intid]; |
109 | } | ||
106 | 110 | ||
107 | /* SPIs */ | 111 | /* SPIs */ |
108 | if (intid <= VGIC_MAX_SPI) | 112 | if (intid <= VGIC_MAX_SPI) { |
113 | intid = array_index_nospec(intid, VGIC_MAX_SPI); | ||
109 | return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS]; | 114 | return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS]; |
115 | } | ||
110 | 116 | ||
111 | /* LPIs */ | 117 | /* LPIs */ |
112 | if (intid >= VGIC_MIN_LPI) | 118 | if (intid >= VGIC_MIN_LPI) |