mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro:
"This is the first pile; another one will come a bit later and will
contain SYSCALL_DEFINE-related patches.
- a bunch of signal-related syscalls (both native and compat)
unified.
- a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE
(fixing several potential problems with missing argument
validation, while we are at it)
- a lot of now-pointless wrappers killed
- a couple of architectures (cris and hexagon) forgot to save
altstack settings into sigframe, even though they used the
(uninitialized) values in sigreturn; fixed.
- microblaze fixes for delivery of multiple signals arriving at once
- saner set of helpers for signal delivery introduced, several
architectures switched to using those."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits)
x86: convert to ksignal
sparc: convert to ksignal
arm: switch to struct ksignal * passing
alpha: pass k_sigaction and siginfo_t using ksignal pointer
burying unused conditionals
make do_sigaltstack() static
arm64: switch to generic old sigaction() (compat-only)
arm64: switch to generic compat rt_sigaction()
arm64: switch compat to generic old sigsuspend
arm64: switch to generic compat rt_sigqueueinfo()
arm64: switch to generic compat rt_sigpending()
arm64: switch to generic compat rt_sigprocmask()
arm64: switch to generic sigaltstack
sparc: switch to generic old sigsuspend
sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE
sparc: kill sign-extending wrappers for native syscalls
kill sparc32_open()
sparc: switch to use of generic old sigaction
sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE
mips: switch to generic sys_fork() and sys_clone()
...
This commit is contained in:
commit
9e2d59ad58
185 changed files with 1363 additions and 4825 deletions
|
|
@ -21,7 +21,8 @@ config ALPHA
|
|||
select GENERIC_STRNLEN_USER
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_SIGALTSTACK
|
||||
select ODD_RT_SIGACTION
|
||||
select OLD_SIGSUSPEND
|
||||
help
|
||||
The Alpha is a 64-bit general-purpose processor designed and
|
||||
marketed by the Digital Equipment Corporation of blessed memory,
|
||||
|
|
|
|||
|
|
@ -22,15 +22,6 @@ struct osf_sigaction {
|
|||
int sa_flags;
|
||||
};
|
||||
|
||||
struct sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
unsigned long sa_flags;
|
||||
sigset_t sa_mask; /* mask last for extensibility */
|
||||
};
|
||||
|
||||
struct k_sigaction {
|
||||
struct sigaction sa;
|
||||
__sigrestore_t ka_restorer;
|
||||
};
|
||||
#define __ARCH_HAS_KA_RESTORER
|
||||
#include <asm/sigcontext.h>
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#define __ARCH_WANT_SYS_OLD_GETRLIMIT
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
#define __ARCH_WANT_SYS_FORK
|
||||
#define __ARCH_WANT_SYS_VFORK
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
|
|
|
|||
|
|
@ -250,7 +250,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||
struct pt_regs *childregs = task_pt_regs(p);
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
struct switch_stack *childstack, *stack;
|
||||
unsigned long settls;
|
||||
|
||||
childstack = ((struct switch_stack *) childregs) - 1;
|
||||
childti->pcb.ksp = (unsigned long) childstack;
|
||||
|
|
|
|||
|
|
@ -112,16 +112,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
|
||||
{
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a signal return; undo the signal stack.
|
||||
*/
|
||||
|
|
@ -282,12 +272,9 @@ give_sigsegv:
|
|||
*/
|
||||
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
|
||||
get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
|
||||
{
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
|
||||
return (void __user *)((sp - frame_size) & -32ul);
|
||||
return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
|
||||
}
|
||||
|
||||
static long
|
||||
|
|
@ -348,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
|||
}
|
||||
|
||||
static int
|
||||
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long oldsp, r26, err = 0;
|
||||
struct sigframe __user *frame;
|
||||
|
||||
oldsp = rdusp();
|
||||
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, oldsp, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return -EFAULT;
|
||||
|
||||
|
|
@ -365,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->ka_restorer) {
|
||||
r26 = (unsigned long) ka->ka_restorer;
|
||||
} else {
|
||||
r26 = (unsigned long) ksig->ka.ka_restorer;
|
||||
if (!r26) {
|
||||
err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
|
||||
err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
|
||||
err |= __put_user(INSN_CALLSYS, frame->retcode+2);
|
||||
|
|
@ -381,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||
|
||||
/* "Return" to the handler */
|
||||
regs->r26 = r26;
|
||||
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->r16 = sig; /* a0: signal number */
|
||||
regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->r16 = ksig->sig; /* a0: signal number */
|
||||
regs->r17 = 0; /* a1: exception code */
|
||||
regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
|
||||
wrusp((unsigned long) frame);
|
||||
|
|
@ -395,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||
}
|
||||
|
||||
static int
|
||||
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long oldsp, r26, err = 0;
|
||||
struct rt_sigframe __user *frame;
|
||||
|
||||
oldsp = rdusp();
|
||||
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, oldsp, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return -EFAULT;
|
||||
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
|
|
@ -421,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->ka_restorer) {
|
||||
r26 = (unsigned long) ka->ka_restorer;
|
||||
} else {
|
||||
r26 = (unsigned long) ksig->ka.ka_restorer;
|
||||
if (!r26) {
|
||||
err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
|
||||
err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
|
||||
frame->retcode+1);
|
||||
|
|
@ -437,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
|
||||
/* "Return" to the handler */
|
||||
regs->r26 = r26;
|
||||
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->r16 = sig; /* a0: signal number */
|
||||
regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->r16 = ksig->sig; /* a0: signal number */
|
||||
regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
|
||||
regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
|
||||
wrusp((unsigned long) frame);
|
||||
|
|
@ -456,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
* OK, we're invoking a handler.
|
||||
*/
|
||||
static inline void
|
||||
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
struct pt_regs * regs)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret) {
|
||||
force_sigsegv(sig, current);
|
||||
return;
|
||||
}
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -514,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19,
|
|||
static void
|
||||
do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
unsigned long single_stepping = ptrace_cancel_bpt(current);
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/* This lets the debugger run, ... */
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
/* ... so re-check the single stepping. */
|
||||
single_stepping |= ptrace_cancel_bpt(current);
|
||||
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* ... so re-check the single stepping. */
|
||||
single_stepping |= ptrace_cancel_bpt(current);
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (r0)
|
||||
syscall_restart(r0, r19, regs, &ka);
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
if (single_stepping)
|
||||
ptrace_set_bpt(current); /* re-set bpt */
|
||||
return;
|
||||
}
|
||||
|
||||
if (r0) {
|
||||
switch (regs->r0) {
|
||||
case ERESTARTNOHAND:
|
||||
case ERESTARTSYS:
|
||||
case ERESTARTNOINTR:
|
||||
/* Reset v0 and a3 and replay syscall. */
|
||||
regs->r0 = r0;
|
||||
regs->r19 = r19;
|
||||
regs->pc -= 4;
|
||||
break;
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
/* Force v0 to the restart syscall and reply. */
|
||||
regs->r0 = __NR_restart_syscall;
|
||||
regs->pc -= 4;
|
||||
break;
|
||||
syscall_restart(r0, r19, regs, &ksig.ka);
|
||||
handle_signal(&ksig, regs);
|
||||
} else {
|
||||
single_stepping |= ptrace_cancel_bpt(current);
|
||||
if (r0) {
|
||||
switch (regs->r0) {
|
||||
case ERESTARTNOHAND:
|
||||
case ERESTARTSYS:
|
||||
case ERESTARTNOINTR:
|
||||
/* Reset v0 and a3 and replay syscall. */
|
||||
regs->r0 = r0;
|
||||
regs->r19 = r19;
|
||||
regs->pc -= 4;
|
||||
break;
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
/* Set v0 to the restart_syscall and replay */
|
||||
regs->r0 = __NR_restart_syscall;
|
||||
regs->pc -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/* If there's no signal to deliver, we just restore the saved mask. */
|
||||
restore_saved_sigmask();
|
||||
if (single_stepping)
|
||||
ptrace_set_bpt(current); /* re-set breakpoint */
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue