Skip to content
Snippets Groups Projects
  • Michael Neuling's avatar
    powerpc/tm: Fix userspace stack corruption on signal delivery for active transactions · 2b3f8e87
    Michael Neuling authored
    
    When in an active transaction that takes a signal, we need to be careful with
    the stack.  It's possible that the stack has moved back up after the tbegin.
    The obvious case here is when the tbegin is called inside a function that
    returns before a tend.  In this case, the stack is part of the checkpointed
    transactional memory state.  If we write over this non transactionally or in
    suspend, we are in trouble because if we get a tm abort, the program counter
    and stack pointer will be back at the tbegin but our in memory stack won't be
    valid anymore.
    
    To avoid this, when taking a signal in an active transaction, we need to use
    the stack pointer from the checkpointed state, rather than the speculated
    state.  This ensures that the signal context (written tm suspended) will be
    written below the stack required for the rollback.  The transaction is aborted
    becuase of the treclaim, so any memory written between the tbegin and the
    signal will be rolled back anyway.
    
    For signals taken in non-TM or suspended mode, we use the
    normal/non-checkpointed stack pointer.
    
    Tested with 64 and 32 bit signals
    
    Signed-off-by: default avatarMichael Neuling <mikey@neuling.org>
    Cc: <stable@vger.kernel.org> # v3.9
    Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
    2b3f8e87
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
signal.h 2.03 KiB
/*
 *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
 *    Extracted from signal_32.c and signal_64.c
 *
 * This file is subject to the terms and conditions of the GNU General
 * Public License.  See the file README.legal in the main directory of
 * this archive for more details.
 */

#ifndef _POWERPC_ARCH_SIGNAL_H
#define _POWERPC_ARCH_SIGNAL_H

extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);

extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
				  size_t frame_size, int is_32);

extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
			   siginfo_t *info, sigset_t *oldset,
			   struct pt_regs *regs);

extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
			      siginfo_t *info, sigset_t *oldset,
			      struct pt_regs *regs);

extern unsigned long copy_fpr_to_user(void __user *to,
				      struct task_struct *task);
extern unsigned long copy_transact_fpr_to_user(void __user *to,
					       struct task_struct *task);
extern unsigned long copy_fpr_from_user(struct task_struct *task,
					void __user *from);
extern unsigned long copy_transact_fpr_from_user(struct task_struct *task,
						 void __user *from);
#ifdef CONFIG_VSX
extern unsigned long copy_vsx_to_user(void __user *to,
				      struct task_struct *task);
extern unsigned long copy_transact_vsx_to_user(void __user *to,
					       struct task_struct *task);
extern unsigned long copy_vsx_from_user(struct task_struct *task,
					void __user *from);
extern unsigned long copy_transact_vsx_from_user(struct task_struct *task,
						 void __user *from);
#endif

#ifdef CONFIG_PPC64

extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
			      siginfo_t *info, sigset_t *set,
			      struct pt_regs *regs);

#else /* CONFIG_PPC64 */

static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
				     siginfo_t *info, sigset_t *set,
				     struct pt_regs *regs)
{
	return -EFAULT;
}

#endif /* !defined(CONFIG_PPC64) */

#endif  /* _POWERPC_ARCH_SIGNAL_H */