diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-12 16:53:47 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-12 16:53:47 (GMT) |
commit | 9925cc1396339da25d5ef477be1f8c41b2391918 (patch) | |
tree | 0644d6a190aacaadae559d38520cb9d49a3348c7 | |
parent | 753a6cb7e4fc112e2f120ca02d167535382e9cec (diff) | |
parent | eb35bdd7bca29a13c8ecd44e6fd747a84ce675db (diff) | |
download | linux-9925cc1396339da25d5ef477be1f8c41b2391918.tar.xz |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon:
"Just a couple of stragglers here:
- fix an issue migrating interrupts on CPU hotplug
- fix a potential information leak of TLS registers across an exec
(Nathan has sent a corresponding patch for arch/arm/ to rmk)"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: flush TLS registers during exec
arm64: use irq_set_affinity with force=false when migrating irqs
-rw-r--r-- | arch/arm64/kernel/irq.c | 12 | ||||
-rw-r--r-- | arch/arm64/kernel/process.c | 18 | ||||
-rw-r--r-- | arch/arm64/kernel/sys_compat.c | 6 |
3 files changed, 28 insertions, 8 deletions
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 0f08dfd..dfa6e3e 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c @@ -97,19 +97,15 @@ static bool migrate_one_irq(struct irq_desc *desc) if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity)) return false; - if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) + if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { + affinity = cpu_online_mask; ret = true; + } - /* - * when using forced irq_set_affinity we must ensure that the cpu - * being offlined is not present in the affinity mask, it may be - * selected as the target CPU otherwise - */ - affinity = cpu_online_mask; c = irq_data_get_irq_chip(d); if (!c->irq_set_affinity) pr_debug("IRQ%u: unable to set affinity\n", d->irq); - else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret) + else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) cpumask_copy(d->affinity, affinity); return ret; diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 1309d64..29d4869 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -230,9 +230,27 @@ void exit_thread(void) { } +static void tls_thread_flush(void) +{ + asm ("msr tpidr_el0, xzr"); + + if (is_compat_task()) { + current->thread.tp_value = 0; + + /* + * We need to ensure ordering between the shadow state and the + * hardware state, so that we don't corrupt the hardware state + * with a stale shadow state during context switch. + */ + barrier(); + asm ("msr tpidrro_el0, xzr"); + } +} + void flush_thread(void) { fpsimd_flush_thread(); + tls_thread_flush(); flush_ptrace_hw_breakpoint(current); } diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index de2b022..dc47e53 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c @@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *regs) case __ARM_NR_compat_set_tls: current->thread.tp_value = regs->regs[0]; + + /* + * Protect against register corruption from context switch. + * See comment in tls_thread_flush. + */ + barrier(); asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); return 0; |