This patch moves arm64's struct thread_info from the task stack into task_struct. This protects thread_info from corruption in the case of stack overflows, and makes its address harder to determine if stack addresses are leaked, making a number of attacks more difficult. Precise detection and handling of overflow is left for subsequent patches. Largely, this involves changing code to store the task_struct in sp_el0, and acquire the thread_info from the task struct. Core code now implements current_thread_info(), and as noted in <linux/sched.h> this relies on offsetof(task_struct, thread_info) == 0, enforced by core code. This change means that the 'tsk' register used in entry.S now points to a task_struct, rather than a thread_info as it used to. To make this clear, the TI_* field offsets are renamed to TSK_TI_*, with asm-offsets appropriately updated to account for the structural change. Userspace clobbers sp_el0, and we can no longer restore this from the stack. Instead, the current task is cached in a per-cpu variable that we can safely access from early assembly as interrupts are disabled (and we are thus not preemptible). Both secondary entry and idle are updated to stash the sp and task pointer separately. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Tested-by: Laura Abbott <labbott@redhat.com> Cc: AKASHI Takahiro <takahiro.akashi@linaro.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: James Morse <james.morse@arm.com> Cc: Kees Cook <keescook@chromium.org> Cc: Suzuki K Poulose <suzuki.poulose@arm.com> Cc: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> This is a modification of Mark Rutland's original patch. Guards to check if CONFIG_THREAD_INFO_IN_TASK is used has been inserted. get_current() for when CONFIG_THREAD_INFO_IN_TASK is not used has been added to arch/arm64/include/asm/current.h. Bug: 38331309 Change-Id: Ic5eae344a7c2baea0864f6ae16be1e9c60c0a74a (cherry picked from commit c02433dd6de32f042cf3ffe476746b1115b8c096) Signed-off-by: Zubin Mithra <zsm@google.com>
93 lines
2.5 KiB
C
93 lines
2.5 KiB
C
/*
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef __ASM_SMP_H
|
|
#define __ASM_SMP_H
|
|
|
|
#include <asm/percpu.h>
|
|
|
|
#include <linux/threads.h>
|
|
#include <linux/cpumask.h>
|
|
#include <linux/thread_info.h>
|
|
|
|
DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
|
|
|
|
/*
|
|
* We don't use this_cpu_read(cpu_number) as that has implicit writes to
|
|
* preempt_count, and associated (compiler) barriers, that we'd like to avoid
|
|
* the expense of. If we're preemptible, the value can be stale at use anyway.
|
|
*/
|
|
#define raw_smp_processor_id() (*this_cpu_ptr(&cpu_number))
|
|
|
|
struct seq_file;
|
|
|
|
/*
|
|
* generate IPI list text
|
|
*/
|
|
extern void show_ipi_list(struct seq_file *p, int prec);
|
|
|
|
/*
|
|
* Called from C code, this handles an IPI.
|
|
*/
|
|
extern void handle_IPI(int ipinr, struct pt_regs *regs);
|
|
|
|
/*
|
|
* Discover the set of possible CPUs and determine their
|
|
* SMP operations.
|
|
*/
|
|
extern void smp_init_cpus(void);
|
|
|
|
/*
|
|
* Provide a function to raise an IPI cross call on CPUs in callmap.
|
|
*/
|
|
extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
|
|
|
|
extern void (*__smp_cross_call)(const struct cpumask *, unsigned int);
|
|
|
|
/*
|
|
* Called from the secondary holding pen, this is the secondary CPU entry point.
|
|
*/
|
|
asmlinkage void secondary_start_kernel(void);
|
|
|
|
/*
|
|
* Initial data for bringing up a secondary CPU.
|
|
*/
|
|
struct secondary_data {
|
|
void *stack;
|
|
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
|
struct task_struct *task;
|
|
#endif
|
|
};
|
|
extern struct secondary_data secondary_data;
|
|
extern void secondary_entry(void);
|
|
|
|
extern void arch_send_call_function_single_ipi(int cpu);
|
|
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
|
|
|
|
#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
|
|
extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);
|
|
#else
|
|
static inline void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
|
|
{
|
|
BUILD_BUG();
|
|
}
|
|
#endif
|
|
|
|
extern int __cpu_disable(void);
|
|
|
|
extern void __cpu_die(unsigned int cpu);
|
|
extern void cpu_die(void);
|
|
|
|
#endif /* ifndef __ASM_SMP_H */
|