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:
@@ -40,12 +40,15 @@ config SPARC
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select MODULES_USE_ELF_RELA
|
||||
select ODD_RT_SIGACTION
|
||||
select OLD_SIGSUSPEND
|
||||
|
||||
config SPARC32
|
||||
def_bool !64BIT
|
||||
select GENERIC_ATOMIC64
|
||||
select CLZ_TAB
|
||||
select HAVE_UID16
|
||||
select OLD_SIGACTION
|
||||
|
||||
config SPARC64
|
||||
def_bool 64BIT
|
||||
@@ -543,6 +546,7 @@ config COMPAT
|
||||
select COMPAT_BINFMT_ELF
|
||||
select HAVE_UID16
|
||||
select ARCH_WANT_OLD_COMPAT_IPC
|
||||
select COMPAT_OLD_SIGACTION
|
||||
|
||||
config SYSVIPC_COMPAT
|
||||
bool
|
||||
|
@@ -18,12 +18,6 @@ struct __old_sigaction32 {
|
||||
unsigned int sa_flags;
|
||||
unsigned sa_restorer; /* not used by Linux/SPARC yet */
|
||||
};
|
||||
|
||||
typedef struct sigaltstack32 {
|
||||
u32 ss_sp;
|
||||
int ss_flags;
|
||||
compat_size_t ss_size;
|
||||
} stack_t32;
|
||||
#endif
|
||||
|
||||
#endif /* !(_COMPAT_SIGNAL_H) */
|
||||
|
@@ -21,10 +21,8 @@
|
||||
*/
|
||||
#define SA_STATIC_ALLOC 0x8000
|
||||
|
||||
struct k_sigaction {
|
||||
struct __new_sigaction sa;
|
||||
void __user *ka_restorer;
|
||||
};
|
||||
#define __ARCH_HAS_KA_RESTORER
|
||||
#define __ARCH_HAS_SA_RESTORER
|
||||
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
#endif /* !(__SPARC_SIGNAL_H) */
|
||||
|
@@ -38,14 +38,11 @@
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
#ifdef __32bit_syscall_numbers__
|
||||
#define __ARCH_WANT_SYS_IPC
|
||||
#else
|
||||
#define __ARCH_WANT_COMPAT_SYS_TIME
|
||||
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
||||
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
|
||||
#define __ARCH_WANT_COMPAT_SYS_SCHED_RR_GET_INTERVAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -153,6 +153,7 @@ struct sigstack {
|
||||
|
||||
#include <asm-generic/signal-defs.h>
|
||||
|
||||
#ifndef __KERNEL__
|
||||
struct __new_sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
unsigned long sa_flags;
|
||||
@@ -166,6 +167,7 @@ struct __old_sigaction {
|
||||
unsigned long sa_flags;
|
||||
void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct sigaltstack {
|
||||
void __user *ss_sp;
|
||||
|
@@ -819,14 +819,6 @@ sys_sparc_pipe:
|
||||
call sparc_pipe
|
||||
mov %l5, %o7
|
||||
|
||||
.align 4
|
||||
.globl sys_sigaltstack
|
||||
sys_sigaltstack:
|
||||
mov %o7, %l5
|
||||
mov %fp, %o2
|
||||
call do_sigaltstack
|
||||
mov %l5, %o7
|
||||
|
||||
.align 4
|
||||
.globl sys_sigstack
|
||||
sys_sigstack:
|
||||
|
@@ -61,7 +61,7 @@ struct rt_signal_frame32 {
|
||||
compat_sigset_t mask;
|
||||
/* __siginfo_fpu_t * */ u32 fpu_save;
|
||||
unsigned int insns[2];
|
||||
stack_t32 stack;
|
||||
compat_stack_t stack;
|
||||
unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
|
||||
/* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
|
||||
siginfo_extra_v8plus_t v8plus;
|
||||
@@ -230,13 +230,11 @@ segv:
|
||||
asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
||||
{
|
||||
struct rt_signal_frame32 __user *sf;
|
||||
unsigned int psr, pc, npc, u_ss_sp;
|
||||
unsigned int psr, pc, npc;
|
||||
compat_uptr_t fpu_save;
|
||||
compat_uptr_t rwin_save;
|
||||
mm_segment_t old_fs;
|
||||
sigset_t set;
|
||||
compat_sigset_t seta;
|
||||
stack_t st;
|
||||
int err, i;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
@@ -295,20 +293,10 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
||||
if (!err && fpu_save)
|
||||
err |= restore_fpu_state(regs, compat_ptr(fpu_save));
|
||||
err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t));
|
||||
err |= __get_user(u_ss_sp, &sf->stack.ss_sp);
|
||||
st.ss_sp = compat_ptr(u_ss_sp);
|
||||
err |= __get_user(st.ss_flags, &sf->stack.ss_flags);
|
||||
err |= __get_user(st.ss_size, &sf->stack.ss_size);
|
||||
err |= compat_restore_altstack(&sf->stack);
|
||||
if (err)
|
||||
goto segv;
|
||||
|
||||
/* It is more difficult to avoid calling this function than to
|
||||
call it and ignore errors. */
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
do_sigaltstack((stack_t __user *) &st, NULL, (unsigned long)sf);
|
||||
set_fs(old_fs);
|
||||
|
||||
err |= __get_user(rwin_save, &sf->rwin_save);
|
||||
if (!err && rwin_save) {
|
||||
if (restore_rwin_state(compat_ptr(rwin_save)))
|
||||
@@ -335,7 +323,7 @@ static int invalid_frame_pointer(void __user *fp, int fplen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
|
||||
static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
||||
@@ -350,12 +338,7 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
|
||||
return (void __user *) -1L;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (sa->sa_flags & SA_ONSTACK) {
|
||||
if (sas_ss_flags(sp) == 0)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
|
||||
sp -= framesize;
|
||||
sp = sigsp(sp, ksig) - framesize;
|
||||
|
||||
/* Always align the stack frame. This handles two cases. First,
|
||||
* sigaltstack need not be mindful of platform specific stack
|
||||
@@ -426,8 +409,8 @@ out_irqs_on:
|
||||
|
||||
}
|
||||
|
||||
static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
int signo, sigset_t *oldset)
|
||||
static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs,
|
||||
sigset_t *oldset)
|
||||
{
|
||||
struct signal_frame32 __user *sf;
|
||||
int i, err, wsaved;
|
||||
@@ -449,10 +432,12 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
sigframe_size += sizeof(__siginfo_rwin_t);
|
||||
|
||||
sf = (struct signal_frame32 __user *)
|
||||
get_sigframe(&ka->sa, regs, sigframe_size);
|
||||
get_sigframe(ksig, regs, sigframe_size);
|
||||
|
||||
if (invalid_frame_pointer(sf, sigframe_size))
|
||||
goto sigill;
|
||||
if (invalid_frame_pointer(sf, sigframe_size)) {
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tail = (sf + 1);
|
||||
|
||||
@@ -526,16 +511,16 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
|
||||
}
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
/* 3. signal handler back-trampoline and parameters */
|
||||
regs->u_regs[UREG_FP] = (unsigned long) sf;
|
||||
regs->u_regs[UREG_I0] = signo;
|
||||
regs->u_regs[UREG_I0] = ksig->sig;
|
||||
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
|
||||
regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
|
||||
|
||||
/* 4. signal handler */
|
||||
regs->tpc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->tnpc = (regs->tpc + 4);
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
@@ -543,8 +528,8 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
}
|
||||
|
||||
/* 5. return to kernel instructions */
|
||||
if (ka->ka_restorer) {
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
|
||||
if (ksig->ka.ka_restorer) {
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
|
||||
} else {
|
||||
unsigned long address = ((unsigned long)&(sf->insns[0]));
|
||||
|
||||
@@ -553,23 +538,14 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/
|
||||
err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
flush_signal_insns(address);
|
||||
}
|
||||
return 0;
|
||||
|
||||
sigill:
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
|
||||
sigsegv:
|
||||
force_sigsegv(signo, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
unsigned long signr, sigset_t *oldset,
|
||||
siginfo_t *info)
|
||||
static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs,
|
||||
sigset_t *oldset)
|
||||
{
|
||||
struct rt_signal_frame32 __user *sf;
|
||||
int i, err, wsaved;
|
||||
@@ -591,10 +567,12 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
sigframe_size += sizeof(__siginfo_rwin_t);
|
||||
|
||||
sf = (struct rt_signal_frame32 __user *)
|
||||
get_sigframe(&ka->sa, regs, sigframe_size);
|
||||
get_sigframe(ksig, regs, sigframe_size);
|
||||
|
||||
if (invalid_frame_pointer(sf, sigframe_size))
|
||||
goto sigill;
|
||||
if (invalid_frame_pointer(sf, sigframe_size)) {
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tail = (sf + 1);
|
||||
|
||||
@@ -639,12 +617,10 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
}
|
||||
|
||||
/* Update the siginfo structure. */
|
||||
err |= copy_siginfo_to_user32(&sf->info, info);
|
||||
err |= copy_siginfo_to_user32(&sf->info, &ksig->info);
|
||||
|
||||
/* Setup sigaltstack */
|
||||
err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
|
||||
err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
|
||||
err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
|
||||
err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]);
|
||||
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: seta.sig[7] = (oldset->sig[3] >> 32);
|
||||
@@ -674,16 +650,16 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
|
||||
}
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
/* 3. signal handler back-trampoline and parameters */
|
||||
regs->u_regs[UREG_FP] = (unsigned long) sf;
|
||||
regs->u_regs[UREG_I0] = signr;
|
||||
regs->u_regs[UREG_I0] = ksig->sig;
|
||||
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
|
||||
regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
|
||||
|
||||
/* 4. signal handler */
|
||||
regs->tpc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->tnpc = (regs->tpc + 4);
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
@@ -691,8 +667,8 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
}
|
||||
|
||||
/* 5. return to kernel instructions */
|
||||
if (ka->ka_restorer)
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
|
||||
if (ksig->ka.ka_restorer)
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
|
||||
else {
|
||||
unsigned long address = ((unsigned long)&(sf->insns[0]));
|
||||
|
||||
@@ -704,36 +680,25 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
/* t 0x10 */
|
||||
err |= __put_user(0x91d02010, &sf->insns[1]);
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
flush_signal_insns(address);
|
||||
}
|
||||
return 0;
|
||||
|
||||
sigill:
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
|
||||
sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
|
||||
siginfo_t *info,
|
||||
sigset_t *oldset, struct pt_regs *regs)
|
||||
static inline void handle_signal32(struct ksignal *ksig,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int err;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
err = setup_rt_frame32(ka, regs, signr, oldset, info);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
err = setup_rt_frame32(ksig, regs, oldset);
|
||||
else
|
||||
err = setup_frame32(ka, regs, signr, oldset);
|
||||
err = setup_frame32(ksig, regs, oldset);
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
signal_setup_done(err, ksig, 0);
|
||||
}
|
||||
|
||||
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
|
||||
@@ -763,50 +728,41 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
|
||||
*/
|
||||
void do_signal32(sigset_t *oldset, struct pt_regs * regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
unsigned long orig_i0;
|
||||
int restart_syscall;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
struct ksignal ksig;
|
||||
unsigned long orig_i0 = 0;
|
||||
int restart_syscall = 0;
|
||||
bool has_handler = get_signal(&ksig);
|
||||
|
||||
restart_syscall = 0;
|
||||
orig_i0 = 0;
|
||||
if (pt_regs_is_syscall(regs) &&
|
||||
(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
|
||||
restart_syscall = 1;
|
||||
orig_i0 = regs->u_regs[UREG_G6];
|
||||
}
|
||||
|
||||
if (signr > 0) {
|
||||
if (has_handler) {
|
||||
if (restart_syscall)
|
||||
syscall_restart32(orig_i0, regs, &ka.sa);
|
||||
handle_signal32(signr, &ka, &info, oldset, regs);
|
||||
return;
|
||||
syscall_restart32(orig_i0, regs, &ksig.ka.sa);
|
||||
handle_signal32(&ksig, regs);
|
||||
} else {
|
||||
if (restart_syscall) {
|
||||
switch (regs->u_regs[UREG_I0]) {
|
||||
case ERESTARTNOHAND:
|
||||
case ERESTARTSYS:
|
||||
case ERESTARTNOINTR:
|
||||
/* replay the system call when we are done */
|
||||
regs->u_regs[UREG_I0] = orig_i0;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
if (restart_syscall &&
|
||||
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
|
||||
regs->u_regs[UREG_I0] == ERESTARTSYS ||
|
||||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
|
||||
/* replay the system call when we are done */
|
||||
regs->u_regs[UREG_I0] = orig_i0;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
if (restart_syscall &&
|
||||
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
|
||||
/* If there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
struct sigstack32 {
|
||||
@@ -856,29 +812,3 @@ asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp)
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp)
|
||||
{
|
||||
stack_t uss, uoss;
|
||||
u32 u_ss_sp = 0;
|
||||
int ret;
|
||||
mm_segment_t old_fs;
|
||||
stack_t32 __user *uss32 = compat_ptr(ussa);
|
||||
stack_t32 __user *uoss32 = compat_ptr(uossa);
|
||||
|
||||
if (ussa && (get_user(u_ss_sp, &uss32->ss_sp) ||
|
||||
__get_user(uss.ss_flags, &uss32->ss_flags) ||
|
||||
__get_user(uss.ss_size, &uss32->ss_size)))
|
||||
return -EFAULT;
|
||||
uss.ss_sp = compat_ptr(u_ss_sp);
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
ret = do_sigaltstack(ussa ? (stack_t __user *) &uss : NULL,
|
||||
uossa ? (stack_t __user *) &uoss : NULL, sp);
|
||||
set_fs(old_fs);
|
||||
if (!ret && uossa && (put_user(ptr_to_compat(uoss.ss_sp), &uoss32->ss_sp) ||
|
||||
__put_user(uoss.ss_flags, &uoss32->ss_flags) ||
|
||||
__put_user(uoss.ss_size, &uoss32->ss_size)))
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
|
@@ -59,18 +59,6 @@ struct rt_signal_frame {
|
||||
#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
|
||||
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
|
||||
|
||||
static int _sigpause_common(old_sigset_t set)
|
||||
{
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, set);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int sys_sigsuspend(old_sigset_t set)
|
||||
{
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
asmlinkage void do_sigreturn(struct pt_regs *regs)
|
||||
{
|
||||
struct signal_frame __user *sf;
|
||||
@@ -141,9 +129,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
|
||||
unsigned int psr, pc, npc;
|
||||
__siginfo_fpu_t __user *fpu_save;
|
||||
__siginfo_rwin_t __user *rwin_save;
|
||||
mm_segment_t old_fs;
|
||||
sigset_t set;
|
||||
stack_t st;
|
||||
int err;
|
||||
|
||||
synchronize_user_stack();
|
||||
@@ -171,8 +157,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
|
||||
if (!err && fpu_save)
|
||||
err |= restore_fpu_state(regs, fpu_save);
|
||||
err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
|
||||
|
||||
err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t));
|
||||
err |= restore_altstack(&sf->stack);
|
||||
|
||||
if (err)
|
||||
goto segv;
|
||||
@@ -180,14 +165,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
|
||||
regs->pc = pc;
|
||||
regs->npc = npc;
|
||||
|
||||
/* It is more difficult to avoid calling this function than to
|
||||
* call it and ignore errors.
|
||||
*/
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf);
|
||||
set_fs(old_fs);
|
||||
|
||||
err |= __get_user(rwin_save, &sf->rwin_save);
|
||||
if (!err && rwin_save) {
|
||||
if (restore_rwin_state(rwin_save))
|
||||
@@ -209,7 +186,7 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
|
||||
{
|
||||
unsigned long sp = regs->u_regs[UREG_FP];
|
||||
|
||||
@@ -221,12 +198,7 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
|
||||
return (void __user *) -1L;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (sa->sa_flags & SA_ONSTACK) {
|
||||
if (sas_ss_flags(sp) == 0)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
|
||||
sp -= framesize;
|
||||
sp = sigsp(sp, ksig) - framesize;
|
||||
|
||||
/* Always align the stack frame. This handles two cases. First,
|
||||
* sigaltstack need not be mindful of platform specific stack
|
||||
@@ -239,8 +211,8 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re
|
||||
return (void __user *) sp;
|
||||
}
|
||||
|
||||
static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
int signo, sigset_t *oldset)
|
||||
static int setup_frame(struct ksignal *ksig, struct pt_regs *regs,
|
||||
sigset_t *oldset)
|
||||
{
|
||||
struct signal_frame __user *sf;
|
||||
int sigframe_size, err, wsaved;
|
||||
@@ -258,10 +230,12 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
sigframe_size += sizeof(__siginfo_rwin_t);
|
||||
|
||||
sf = (struct signal_frame __user *)
|
||||
get_sigframe(&ka->sa, regs, sigframe_size);
|
||||
get_sigframe(ksig, regs, sigframe_size);
|
||||
|
||||
if (invalid_frame_pointer(sf, sigframe_size))
|
||||
goto sigill_and_return;
|
||||
if (invalid_frame_pointer(sf, sigframe_size)) {
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tail = sf + 1;
|
||||
|
||||
@@ -300,21 +274,21 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
|
||||
}
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
/* 3. signal handler back-trampoline and parameters */
|
||||
regs->u_regs[UREG_FP] = (unsigned long) sf;
|
||||
regs->u_regs[UREG_I0] = signo;
|
||||
regs->u_regs[UREG_I0] = ksig->sig;
|
||||
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
|
||||
regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
|
||||
|
||||
/* 4. signal handler */
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->npc = (regs->pc + 4);
|
||||
|
||||
/* 5. return to kernel instructions */
|
||||
if (ka->ka_restorer)
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
|
||||
if (ksig->ka.ka_restorer)
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
|
||||
else {
|
||||
regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);
|
||||
|
||||
@@ -324,24 +298,16 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
/* t 0x10 */
|
||||
err |= __put_user(0x91d02010, &sf->insns[1]);
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
/* Flush instruction space. */
|
||||
flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
|
||||
}
|
||||
return 0;
|
||||
|
||||
sigill_and_return:
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
|
||||
sigsegv:
|
||||
force_sigsegv(signo, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
int signo, sigset_t *oldset, siginfo_t *info)
|
||||
static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
|
||||
sigset_t *oldset)
|
||||
{
|
||||
struct rt_signal_frame __user *sf;
|
||||
int sigframe_size, wsaved;
|
||||
@@ -357,9 +323,11 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
if (wsaved)
|
||||
sigframe_size += sizeof(__siginfo_rwin_t);
|
||||
sf = (struct rt_signal_frame __user *)
|
||||
get_sigframe(&ka->sa, regs, sigframe_size);
|
||||
if (invalid_frame_pointer(sf, sigframe_size))
|
||||
goto sigill;
|
||||
get_sigframe(ksig, regs, sigframe_size);
|
||||
if (invalid_frame_pointer(sf, sigframe_size)) {
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tail = sf + 1;
|
||||
err = __put_user(regs->pc, &sf->regs.pc);
|
||||
@@ -391,9 +359,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
|
||||
|
||||
/* Setup sigaltstack */
|
||||
err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
|
||||
err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
|
||||
err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
|
||||
err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]);
|
||||
|
||||
if (!wsaved) {
|
||||
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
|
||||
@@ -405,21 +371,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __copy_to_user(sf, rp, sizeof(struct reg_window32));
|
||||
}
|
||||
|
||||
err |= copy_siginfo_to_user(&sf->info, info);
|
||||
err |= copy_siginfo_to_user(&sf->info, &ksig->info);
|
||||
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
regs->u_regs[UREG_FP] = (unsigned long) sf;
|
||||
regs->u_regs[UREG_I0] = signo;
|
||||
regs->u_regs[UREG_I0] = ksig->sig;
|
||||
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
|
||||
regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
|
||||
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->npc = (regs->pc + 4);
|
||||
|
||||
if (ka->ka_restorer)
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
|
||||
if (ksig->ka.ka_restorer)
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
|
||||
else {
|
||||
regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);
|
||||
|
||||
@@ -429,38 +395,25 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
/* t 0x10 */
|
||||
err |= __put_user(0x91d02010, &sf->insns[1]);
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
/* Flush instruction space. */
|
||||
flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
|
||||
}
|
||||
return 0;
|
||||
|
||||
sigill:
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
|
||||
sigsegv:
|
||||
force_sigsegv(signo, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_signal(unsigned long signr, 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 err;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
err = setup_rt_frame(ka, regs, signr, oldset, info);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
err = setup_rt_frame(ksig, regs, oldset);
|
||||
else
|
||||
err = setup_frame(ka, regs, signr, oldset);
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
err = setup_frame(ksig, regs, oldset);
|
||||
signal_setup_done(err, ksig, 0);
|
||||
}
|
||||
|
||||
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
@@ -490,10 +443,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
int restart_syscall;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
bool has_handler;
|
||||
|
||||
/* It's a lot of work and synchronization to add a new ptrace
|
||||
* register for GDB to save and restore in order to get
|
||||
@@ -516,7 +468,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||
if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
|
||||
regs->u_regs[UREG_G6] = orig_i0;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
has_handler = get_signal(&ksig);
|
||||
|
||||
/* If the debugger messes with the program counter, it clears
|
||||
* the software "in syscall" bit, directing us to not perform
|
||||
@@ -528,35 +480,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||
orig_i0 = regs->u_regs[UREG_G6];
|
||||
}
|
||||
|
||||
|
||||
if (signr > 0) {
|
||||
if (has_handler) {
|
||||
if (restart_syscall)
|
||||
syscall_restart(orig_i0, regs, &ka.sa);
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
return;
|
||||
syscall_restart(orig_i0, regs, &ksig.ka.sa);
|
||||
handle_signal(&ksig, regs);
|
||||
} else {
|
||||
if (restart_syscall) {
|
||||
switch (regs->u_regs[UREG_I0]) {
|
||||
case ERESTARTNOHAND:
|
||||
case ERESTARTSYS:
|
||||
case ERESTARTNOINTR:
|
||||
/* replay the system call when we are done */
|
||||
regs->u_regs[UREG_I0] = orig_i0;
|
||||
regs->pc -= 4;
|
||||
regs->npc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||
regs->pc -= 4;
|
||||
regs->npc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
if (restart_syscall &&
|
||||
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
|
||||
regs->u_regs[UREG_I0] == ERESTARTSYS ||
|
||||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
|
||||
/* replay the system call when we are done */
|
||||
regs->u_regs[UREG_I0] = orig_i0;
|
||||
regs->pc -= 4;
|
||||
regs->npc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
if (restart_syscall &&
|
||||
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||
regs->pc -= 4;
|
||||
regs->npc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
|
||||
/* if there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
|
||||
|
@@ -236,23 +236,6 @@ struct rt_signal_frame {
|
||||
__siginfo_rwin_t *rwin_save;
|
||||
};
|
||||
|
||||
static long _sigpause_common(old_sigset_t set)
|
||||
{
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, set);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage long sys_sigpause(unsigned int set)
|
||||
{
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
asmlinkage long sys_sigsuspend(old_sigset_t set)
|
||||
{
|
||||
return _sigpause_common(set);
|
||||
}
|
||||
|
||||
void do_rt_sigreturn(struct pt_regs *regs)
|
||||
{
|
||||
struct rt_signal_frame __user *sf;
|
||||
@@ -295,7 +278,8 @@ void do_rt_sigreturn(struct pt_regs *regs)
|
||||
err |= restore_fpu_state(regs, fpu_save);
|
||||
|
||||
err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
|
||||
if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
|
||||
err |= restore_altstack(&sf->stack);
|
||||
if (err)
|
||||
goto segv;
|
||||
|
||||
err |= __get_user(rwin_save, &sf->rwin_save);
|
||||
@@ -324,7 +308,7 @@ static int invalid_frame_pointer(void __user *fp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
|
||||
{
|
||||
unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
|
||||
|
||||
@@ -336,12 +320,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
|
||||
return (void __user *) -1L;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (sas_ss_flags(sp) == 0)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
|
||||
sp -= framesize;
|
||||
sp = sigsp(sp, ksig) - framesize;
|
||||
|
||||
/* Always align the stack frame. This handles two cases. First,
|
||||
* sigaltstack need not be mindful of platform specific stack
|
||||
@@ -355,8 +334,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *
|
||||
}
|
||||
|
||||
static inline int
|
||||
setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
int signo, sigset_t *oldset, siginfo_t *info)
|
||||
setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
struct rt_signal_frame __user *sf;
|
||||
int wsaved, err, sf_size;
|
||||
@@ -374,10 +352,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
if (wsaved)
|
||||
sf_size += sizeof(__siginfo_rwin_t);
|
||||
sf = (struct rt_signal_frame __user *)
|
||||
get_sigframe(ka, regs, sf_size);
|
||||
get_sigframe(ksig, regs, sf_size);
|
||||
|
||||
if (invalid_frame_pointer (sf))
|
||||
goto sigill;
|
||||
if (invalid_frame_pointer (sf)) {
|
||||
do_exit(SIGILL); /* won't return, actually */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tail = (sf + 1);
|
||||
|
||||
@@ -403,11 +383,9 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
}
|
||||
|
||||
/* Setup sigaltstack */
|
||||
err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
|
||||
err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
|
||||
err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
|
||||
err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]);
|
||||
|
||||
err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
|
||||
err |= copy_to_user(&sf->mask, sigmask_to_save(), sizeof(sigset_t));
|
||||
|
||||
if (!wsaved) {
|
||||
err |= copy_in_user((u64 __user *)sf,
|
||||
@@ -420,18 +398,18 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
rp = ¤t_thread_info()->reg_window[wsaved - 1];
|
||||
err |= copy_to_user(sf, rp, sizeof(struct reg_window));
|
||||
}
|
||||
if (info)
|
||||
err |= copy_siginfo_to_user(&sf->info, info);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
err |= copy_siginfo_to_user(&sf->info, &ksig->info);
|
||||
else {
|
||||
err |= __put_user(signo, &sf->info.si_signo);
|
||||
err |= __put_user(ksig->sig, &sf->info.si_signo);
|
||||
err |= __put_user(SI_NOINFO, &sf->info.si_code);
|
||||
}
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return err;
|
||||
|
||||
/* 3. signal handler back-trampoline and parameters */
|
||||
regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
|
||||
regs->u_regs[UREG_I0] = signo;
|
||||
regs->u_regs[UREG_I0] = ksig->sig;
|
||||
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
|
||||
|
||||
/* The sigcontext is passed in this way because of how it
|
||||
@@ -441,37 +419,15 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
|
||||
|
||||
/* 5. signal handler */
|
||||
regs->tpc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->tnpc = (regs->tpc + 4);
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
/* 4. return to kernel instructions */
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
|
||||
regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
|
||||
return 0;
|
||||
|
||||
sigill:
|
||||
do_exit(SIGILL);
|
||||
return -EINVAL;
|
||||
|
||||
sigsegv:
|
||||
force_sigsegv(signo, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
|
||||
siginfo_t *info,
|
||||
sigset_t *oldset, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = setup_rt_frame(ka, regs, signr, oldset,
|
||||
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
@@ -501,11 +457,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
int restart_syscall;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
bool has_handler;
|
||||
|
||||
/* It's a lot of work and synchronization to add a new ptrace
|
||||
* register for GDB to save and restore in order to get
|
||||
@@ -531,13 +485,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
extern void do_signal32(sigset_t *, struct pt_regs *);
|
||||
do_signal32(oldset, regs);
|
||||
extern void do_signal32(struct pt_regs *);
|
||||
do_signal32(regs);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
has_handler = get_signal(&ksig);
|
||||
|
||||
restart_syscall = 0;
|
||||
if (pt_regs_is_syscall(regs) &&
|
||||
@@ -546,34 +500,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||
orig_i0 = regs->u_regs[UREG_G6];
|
||||
}
|
||||
|
||||
if (signr > 0) {
|
||||
if (has_handler) {
|
||||
if (restart_syscall)
|
||||
syscall_restart(orig_i0, regs, &ka.sa);
|
||||
handle_signal(signr, &ka, &info, oldset, regs);
|
||||
return;
|
||||
syscall_restart(orig_i0, regs, &ksig.ka.sa);
|
||||
signal_setup_done(setup_rt_frame(&ksig, regs), &ksig, 0);
|
||||
} else {
|
||||
if (restart_syscall) {
|
||||
switch (regs->u_regs[UREG_I0]) {
|
||||
case ERESTARTNOHAND:
|
||||
case ERESTARTSYS:
|
||||
case ERESTARTNOINTR:
|
||||
/* replay the system call when we are done */
|
||||
regs->u_regs[UREG_I0] = orig_i0;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
if (restart_syscall &&
|
||||
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
|
||||
regs->u_regs[UREG_I0] == ERESTARTSYS ||
|
||||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
|
||||
/* replay the system call when we are done */
|
||||
regs->u_regs[UREG_I0] = orig_i0;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
if (restart_syscall &&
|
||||
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||
regs->tpc -= 4;
|
||||
regs->tnpc -= 4;
|
||||
pt_regs_clear_syscall(regs);
|
||||
}
|
||||
|
||||
/* If there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
|
||||
|
@@ -36,108 +36,22 @@ STUB: sra REG1, 0, REG1; \
|
||||
jmpl %g1 + %lo(SYSCALL), %g0; \
|
||||
sra REG3, 0, REG3
|
||||
|
||||
#define SIGN4(STUB,SYSCALL,REG1,REG2,REG3,REG4) \
|
||||
.align 32; \
|
||||
.globl STUB; \
|
||||
STUB: sra REG1, 0, REG1; \
|
||||
sethi %hi(SYSCALL), %g1; \
|
||||
sra REG2, 0, REG2; \
|
||||
sra REG3, 0, REG3; \
|
||||
jmpl %g1 + %lo(SYSCALL), %g0; \
|
||||
sra REG4, 0, REG4
|
||||
|
||||
SIGN1(sys32_exit, sparc_exit, %o0)
|
||||
SIGN1(sys32_exit_group, sparc_exit_group, %o0)
|
||||
SIGN1(sys32_wait4, compat_sys_wait4, %o2)
|
||||
SIGN1(sys32_creat, sys_creat, %o1)
|
||||
SIGN1(sys32_mknod, sys_mknod, %o1)
|
||||
SIGN1(sys32_umount, sys_umount, %o1)
|
||||
SIGN1(sys32_signal, sys_signal, %o0)
|
||||
SIGN1(sys32_access, sys_access, %o1)
|
||||
SIGN1(sys32_msync, sys_msync, %o2)
|
||||
SIGN2(sys32_reboot, sys_reboot, %o0, %o1)
|
||||
SIGN1(sys32_setitimer, compat_sys_setitimer, %o0)
|
||||
SIGN1(sys32_getitimer, compat_sys_getitimer, %o0)
|
||||
SIGN1(sys32_sethostname, sys_sethostname, %o1)
|
||||
SIGN1(sys32_swapon, sys_swapon, %o1)
|
||||
SIGN1(sys32_sigaction, compat_sys_sigaction, %o0)
|
||||
SIGN1(sys32_rt_sigaction, compat_sys_rt_sigaction, %o0)
|
||||
SIGN1(sys32_sigprocmask, compat_sys_sigprocmask, %o0)
|
||||
SIGN1(sys32_rt_sigprocmask, compat_sys_rt_sigprocmask, %o0)
|
||||
SIGN2(sys32_rt_sigqueueinfo, compat_sys_rt_sigqueueinfo, %o0, %o1)
|
||||
SIGN1(sys32_getrusage, compat_sys_getrusage, %o0)
|
||||
SIGN1(sys32_setxattr, sys_setxattr, %o4)
|
||||
SIGN1(sys32_lsetxattr, sys_lsetxattr, %o4)
|
||||
SIGN1(sys32_fsetxattr, sys_fsetxattr, %o4)
|
||||
SIGN1(sys32_fgetxattr, sys_fgetxattr, %o0)
|
||||
SIGN1(sys32_flistxattr, sys_flistxattr, %o0)
|
||||
SIGN1(sys32_fremovexattr, sys_fremovexattr, %o0)
|
||||
SIGN2(sys32_tkill, sys_tkill, %o0, %o1)
|
||||
SIGN1(sys32_epoll_create, sys_epoll_create, %o0)
|
||||
SIGN3(sys32_epoll_ctl, sys_epoll_ctl, %o0, %o1, %o2)
|
||||
SIGN3(sys32_epoll_wait, sys_epoll_wait, %o0, %o2, %o3)
|
||||
SIGN1(sys32_readahead, compat_sys_readahead, %o0)
|
||||
SIGN2(sys32_fadvise64, compat_sys_fadvise64, %o0, %o4)
|
||||
SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5)
|
||||
SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
|
||||
SIGN1(sys32_mlockall, sys_mlockall, %o0)
|
||||
SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
|
||||
SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
|
||||
SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
|
||||
SIGN1(sys32_mq_open, compat_sys_mq_open, %o1)
|
||||
SIGN1(sys32_select, compat_sys_select, %o0)
|
||||
SIGN1(sys32_mkdir, sys_mkdir, %o1)
|
||||
SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5)
|
||||
SIGN1(sys32_sysfs, compat_sys_sysfs, %o0)
|
||||
SIGN2(sys32_sendfile, compat_sys_sendfile, %o0, %o1)
|
||||
SIGN2(sys32_sendfile64, sys_sendfile, %o0, %o1)
|
||||
SIGN1(sys32_prctl, sys_prctl, %o0)
|
||||
SIGN1(sys32_sched_rr_get_interval, compat_sys_sched_rr_get_interval, %o0)
|
||||
SIGN2(sys32_waitpid, sys_waitpid, %o0, %o2)
|
||||
SIGN1(sys32_getgroups, sys_getgroups, %o0)
|
||||
SIGN1(sys32_getpgid, sys_getpgid, %o0)
|
||||
SIGN2(sys32_getpriority, sys_getpriority, %o0, %o1)
|
||||
SIGN1(sys32_getsid, sys_getsid, %o0)
|
||||
SIGN2(sys32_kill, sys_kill, %o0, %o1)
|
||||
SIGN1(sys32_nice, sys_nice, %o0)
|
||||
SIGN1(sys32_lseek, sys_lseek, %o1)
|
||||
SIGN2(sys32_open, sparc32_open, %o1, %o2)
|
||||
SIGN1(sys32_readlink, sys_readlink, %o2)
|
||||
SIGN1(sys32_sched_get_priority_max, sys_sched_get_priority_max, %o0)
|
||||
SIGN1(sys32_sched_get_priority_min, sys_sched_get_priority_min, %o0)
|
||||
SIGN1(sys32_sched_getparam, sys_sched_getparam, %o0)
|
||||
SIGN1(sys32_sched_getscheduler, sys_sched_getscheduler, %o0)
|
||||
SIGN1(sys32_sched_setparam, sys_sched_setparam, %o0)
|
||||
SIGN2(sys32_sched_setscheduler, sys_sched_setscheduler, %o0, %o1)
|
||||
SIGN1(sys32_getdomainname, sys_getdomainname, %o1)
|
||||
SIGN1(sys32_setdomainname, sys_setdomainname, %o1)
|
||||
SIGN1(sys32_setgroups, sys_setgroups, %o0)
|
||||
SIGN2(sys32_setpgid, sys_setpgid, %o0, %o1)
|
||||
SIGN3(sys32_setpriority, sys_setpriority, %o0, %o1, %o2)
|
||||
SIGN1(sys32_ssetmask, sys_ssetmask, %o0)
|
||||
SIGN2(sys32_syslog, sys_syslog, %o0, %o2)
|
||||
SIGN1(sys32_umask, sys_umask, %o0)
|
||||
SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2)
|
||||
SIGN1(sys32_sendto, sys_sendto, %o0)
|
||||
SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0)
|
||||
SIGN3(sys32_socket, sys_socket, %o0, %o1, %o2)
|
||||
SIGN2(sys32_connect, sys_connect, %o0, %o2)
|
||||
SIGN2(sys32_bind, sys_bind, %o0, %o2)
|
||||
SIGN2(sys32_listen, sys_listen, %o0, %o1)
|
||||
SIGN1(sys32_recvmsg, compat_sys_recvmsg, %o0)
|
||||
SIGN1(sys32_sendmsg, compat_sys_sendmsg, %o0)
|
||||
SIGN2(sys32_shutdown, sys_shutdown, %o0, %o1)
|
||||
SIGN3(sys32_socketpair, sys_socketpair, %o0, %o1, %o2)
|
||||
SIGN1(sys32_getpeername, sys_getpeername, %o0)
|
||||
SIGN1(sys32_getsockname, sys_getsockname, %o0)
|
||||
SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
|
||||
SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
|
||||
SIGN2(sys32_splice, sys_splice, %o0, %o2)
|
||||
SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
|
||||
SIGN2(sys32_tee, sys_tee, %o0, %o1)
|
||||
SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
|
||||
SIGN1(sys32_truncate, sys_truncate, %o1)
|
||||
SIGN1(sys32_ftruncate, sys_ftruncate, %o1)
|
||||
|
||||
.globl sys32_mmap2
|
||||
sys32_mmap2:
|
||||
|
@@ -206,133 +206,19 @@ asmlinkage long compat_sys_fstatat64(unsigned int dfd,
|
||||
return cp_compat_stat64(&stat, statbuf);
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
|
||||
COMPAT_SYSCALL_DEFINE3(sparc_sigaction, int, sig,
|
||||
struct compat_old_sigaction __user *,act,
|
||||
struct compat_old_sigaction __user *,oact)
|
||||
{
|
||||
return sys_sysfs(option, arg1, arg2);
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_rt_sigprocmask(int how,
|
||||
compat_sigset_t __user *set,
|
||||
compat_sigset_t __user *oset,
|
||||
compat_size_t sigsetsize)
|
||||
{
|
||||
sigset_t s;
|
||||
compat_sigset_t s32;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
if (set) {
|
||||
if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
|
||||
return -EFAULT;
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
|
||||
case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
|
||||
case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
|
||||
case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
|
||||
}
|
||||
}
|
||||
set_fs (KERNEL_DS);
|
||||
ret = sys_rt_sigprocmask(how,
|
||||
set ? (sigset_t __user *) &s : NULL,
|
||||
oset ? (sigset_t __user *) &s : NULL,
|
||||
sigsetsize);
|
||||
set_fs (old_fs);
|
||||
if (ret) return ret;
|
||||
if (oset) {
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
|
||||
case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
|
||||
case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
|
||||
case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
|
||||
}
|
||||
if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
|
||||
compat_size_t sigsetsize)
|
||||
{
|
||||
sigset_t s;
|
||||
compat_sigset_t s32;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs (KERNEL_DS);
|
||||
ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
|
||||
set_fs (old_fs);
|
||||
if (!ret) {
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
|
||||
case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
|
||||
case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
|
||||
case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
|
||||
}
|
||||
if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
|
||||
struct compat_siginfo __user *uinfo)
|
||||
{
|
||||
siginfo_t info;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
if (copy_siginfo_from_user32(&info, uinfo))
|
||||
return -EFAULT;
|
||||
|
||||
set_fs (KERNEL_DS);
|
||||
ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
|
||||
set_fs (old_fs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
|
||||
struct old_sigaction32 __user *oact)
|
||||
{
|
||||
struct k_sigaction new_ka, old_ka;
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(sig >= 0);
|
||||
sig = -sig;
|
||||
|
||||
if (act) {
|
||||
compat_old_sigset_t mask;
|
||||
u32 u_handler, u_restorer;
|
||||
|
||||
ret = get_user(u_handler, &act->sa_handler);
|
||||
new_ka.sa.sa_handler = compat_ptr(u_handler);
|
||||
ret |= __get_user(u_restorer, &act->sa_restorer);
|
||||
new_ka.sa.sa_restorer = compat_ptr(u_restorer);
|
||||
ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
ret |= __get_user(mask, &act->sa_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
new_ka.ka_restorer = NULL;
|
||||
siginitset(&new_ka.sa.sa_mask, mask);
|
||||
}
|
||||
|
||||
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
|
||||
|
||||
if (!ret && oact) {
|
||||
ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
|
||||
ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
|
||||
ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return compat_sys_sigaction(-sig, act, oact);
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_rt_sigaction(int sig,
|
||||
struct sigaction32 __user *act,
|
||||
struct sigaction32 __user *oact,
|
||||
void __user *restorer,
|
||||
compat_size_t sigsetsize)
|
||||
COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig,
|
||||
struct compat_sigaction __user *,act,
|
||||
struct compat_sigaction __user *,oact,
|
||||
void __user *,restorer,
|
||||
compat_size_t,sigsetsize)
|
||||
{
|
||||
struct k_sigaction new_ka, old_ka;
|
||||
int ret;
|
||||
@@ -349,12 +235,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
|
||||
ret = get_user(u_handler, &act->sa_handler);
|
||||
new_ka.sa.sa_handler = compat_ptr(u_handler);
|
||||
ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
|
||||
case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
|
||||
case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
|
||||
case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
|
||||
}
|
||||
sigset_from_compat(&new_ka.sa.sa_mask, &set32);
|
||||
ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
ret |= __get_user(u_restorer, &act->sa_restorer);
|
||||
new_ka.sa.sa_restorer = compat_ptr(u_restorer);
|
||||
@@ -365,12 +246,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
|
||||
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
|
||||
|
||||
if (!ret && oact) {
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
|
||||
case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
|
||||
case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
|
||||
case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
|
||||
}
|
||||
sigset_to_compat(&set32, &old_ka.sa.sa_mask);
|
||||
ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
|
||||
ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
|
||||
ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
@@ -382,35 +258,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
asmlinkage long sys32_init_module(void __user *umod, u32 len,
|
||||
const char __user *uargs)
|
||||
{
|
||||
return sys_init_module(umod, len, uargs);
|
||||
}
|
||||
|
||||
asmlinkage long sys32_delete_module(const char __user *name_user,
|
||||
unsigned int flags)
|
||||
{
|
||||
return sys_delete_module(name_user, flags);
|
||||
}
|
||||
|
||||
#else /* CONFIG_MODULES */
|
||||
|
||||
asmlinkage long sys32_init_module(const char __user *name_user,
|
||||
struct module __user *mod_user)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
asmlinkage long sys32_delete_module(const char __user *name_user)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
|
||||
char __user *ubuf,
|
||||
compat_size_t count,
|
||||
@@ -456,16 +303,6 @@ long compat_sys_fadvise64_64(int fd,
|
||||
advice);
|
||||
}
|
||||
|
||||
/* This is just a version for 32-bit applications which does
|
||||
* not force O_LARGEFILE on.
|
||||
*/
|
||||
|
||||
asmlinkage long sparc32_open(const char __user *filename,
|
||||
int flags, int mode)
|
||||
{
|
||||
return do_sys_open(AT_FDCWD, filename, flags, mode);
|
||||
}
|
||||
|
||||
long sys32_lookup_dcookie(unsigned long cookie_high,
|
||||
unsigned long cookie_low,
|
||||
char __user *buf, size_t len)
|
||||
|
@@ -160,49 +160,19 @@ sparc_breakpoint (struct pt_regs *regs)
|
||||
#endif
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
sparc_sigaction (int sig, const struct old_sigaction __user *act,
|
||||
struct old_sigaction __user *oact)
|
||||
SYSCALL_DEFINE3(sparc_sigaction, int, sig,
|
||||
struct old_sigaction __user *,act,
|
||||
struct old_sigaction __user *,oact)
|
||||
{
|
||||
struct k_sigaction new_ka, old_ka;
|
||||
int ret;
|
||||
|
||||
WARN_ON_ONCE(sig >= 0);
|
||||
sig = -sig;
|
||||
|
||||
if (act) {
|
||||
unsigned long mask;
|
||||
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||
__get_user(mask, &act->sa_mask))
|
||||
return -EFAULT;
|
||||
siginitset(&new_ka.sa.sa_mask, mask);
|
||||
new_ka.ka_restorer = NULL;
|
||||
}
|
||||
|
||||
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
|
||||
|
||||
if (!ret && oact) {
|
||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return sys_sigaction(-sig, act, oact);
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
sys_rt_sigaction(int sig,
|
||||
const struct sigaction __user *act,
|
||||
struct sigaction __user *oact,
|
||||
void __user *restorer,
|
||||
size_t sigsetsize)
|
||||
SYSCALL_DEFINE5(rt_sigaction, int, sig,
|
||||
const struct sigaction __user *, act,
|
||||
struct sigaction __user *, oact,
|
||||
void __user *, restorer,
|
||||
size_t, sigsetsize)
|
||||
{
|
||||
struct k_sigaction new_ka, old_ka;
|
||||
int ret;
|
||||
|
@@ -25,16 +25,10 @@ sys_nis_syscall:
|
||||
sys_memory_ordering:
|
||||
ba,pt %xcc, sparc_memory_ordering
|
||||
add %sp, PTREGS_OFF, %o1
|
||||
sys_sigaltstack:
|
||||
ba,pt %xcc, do_sigaltstack
|
||||
add %i6, STACK_BIAS, %o2
|
||||
#ifdef CONFIG_COMPAT
|
||||
sys32_sigstack:
|
||||
ba,pt %xcc, do_sys32_sigstack
|
||||
mov %i6, %o2
|
||||
sys32_sigaltstack:
|
||||
ba,pt %xcc, do_sys32_sigaltstack
|
||||
mov %i6, %o2
|
||||
#endif
|
||||
.align 32
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@@ -3,8 +3,8 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/signal.h>
|
||||
#include <asm/utrap.h>
|
||||
#include <asm/signal.h>
|
||||
|
||||
extern asmlinkage unsigned long sys_getpagesize(void);
|
||||
extern asmlinkage long sparc_pipe(struct pt_regs *regs);
|
||||
@@ -36,8 +36,6 @@ extern asmlinkage long sys_rt_sigaction(int sig,
|
||||
|
||||
extern asmlinkage void sparc64_set_context(struct pt_regs *regs);
|
||||
extern asmlinkage void sparc64_get_context(struct pt_regs *regs);
|
||||
extern asmlinkage long sys_sigpause(unsigned int set);
|
||||
extern asmlinkage long sys_sigsuspend(old_sigset_t set);
|
||||
extern void do_rt_sigreturn(struct pt_regs *regs);
|
||||
|
||||
#endif /* _SYSTBLS_H */
|
||||
|
@@ -55,7 +55,7 @@ sys_call_table:
|
||||
/*180*/ .long sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_sigpending, sys_ni_syscall
|
||||
/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname
|
||||
/*190*/ .long sys_init_module, sys_personality, sparc_remap_file_pages, sys_epoll_create, sys_epoll_ctl
|
||||
/*195*/ .long sys_epoll_wait, sys_ioprio_set, sys_getppid, sparc_sigaction, sys_sgetmask
|
||||
/*195*/ .long sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_sparc_sigaction, sys_sgetmask
|
||||
/*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_old_readdir
|
||||
/*205*/ .long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64
|
||||
/*210*/ .long sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo
|
||||
|
@@ -18,63 +18,63 @@
|
||||
|
||||
.globl sys_call_table32
|
||||
sys_call_table32:
|
||||
/*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write
|
||||
/*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link
|
||||
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod
|
||||
/*15*/ .word sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys32_lseek
|
||||
/*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write
|
||||
/*5*/ .word compat_sys_open, sys_close, compat_sys_wait4, sys_creat, sys_link
|
||||
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
|
||||
/*15*/ .word sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys_lseek
|
||||
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
|
||||
/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause
|
||||
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
|
||||
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
|
||||
/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, compat_sys_sigaltstack, sys_pause
|
||||
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
|
||||
.word sys_chown, sys_sync, sys_kill, compat_sys_newstat, sys32_sendfile
|
||||
/*40*/ .word compat_sys_newlstat, sys_dup, sys_sparc_pipe, compat_sys_times, sys_getuid
|
||||
.word sys32_umount, sys_setgid16, sys_getgid16, sys32_signal, sys_geteuid16
|
||||
.word sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16
|
||||
/*50*/ .word sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl
|
||||
.word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve
|
||||
/*60*/ .word sys32_umask, sys_chroot, compat_sys_newfstat, compat_sys_fstat64, sys_getpagesize
|
||||
.word sys32_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid
|
||||
.word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve
|
||||
/*60*/ .word sys_umask, sys_chroot, compat_sys_newfstat, compat_sys_fstat64, sys_getpagesize
|
||||
.word sys_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid
|
||||
/*70*/ .word sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect
|
||||
.word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys_getgroups16
|
||||
/*80*/ .word sys_setgroups16, sys_getpgrp, sys32_setgroups, sys32_setitimer, sys32_ftruncate64
|
||||
.word sys32_swapon, sys32_getitimer, sys_setuid, sys32_sethostname, sys_setgid
|
||||
/*80*/ .word sys_setgroups16, sys_getpgrp, sys_setgroups, compat_sys_setitimer, sys32_ftruncate64
|
||||
.word sys_swapon, compat_sys_getitimer, sys_setuid, sys_sethostname, sys_setgid
|
||||
/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
|
||||
.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
|
||||
/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
|
||||
.word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
|
||||
.word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
|
||||
/*100*/ .word sys_getpriority, sys32_rt_sigreturn, compat_sys_rt_sigaction, compat_sys_rt_sigprocmask, compat_sys_rt_sigpending
|
||||
.word compat_sys_rt_sigtimedwait, compat_sys_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
|
||||
/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
|
||||
.word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
|
||||
.word sys_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
|
||||
/*120*/ .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
|
||||
.word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys32_truncate
|
||||
/*130*/ .word sys32_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
|
||||
.word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
|
||||
/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
|
||||
.word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
|
||||
.word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
|
||||
/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
|
||||
.word sys_nis_syscall, sys_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
|
||||
/*140*/ .word sys_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
|
||||
.word compat_sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
|
||||
/*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
|
||||
.word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
|
||||
/*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys32_getdomainname, sys32_setdomainname, sys_nis_syscall
|
||||
.word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys32_setxattr
|
||||
/*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents
|
||||
.word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr
|
||||
/*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
|
||||
.word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_newuname
|
||||
/*190*/ .word sys32_init_module, sys_sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl
|
||||
.word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask
|
||||
/*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
|
||||
.word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64
|
||||
/*210*/ .word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, compat_sys_sysinfo
|
||||
.word compat_sys_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex
|
||||
/*220*/ .word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
|
||||
.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
|
||||
/*230*/ .word sys32_select, compat_sys_time, sys32_splice, compat_sys_stime, compat_sys_statfs64
|
||||
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
|
||||
/*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
|
||||
.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
|
||||
/*250*/ .word sys_mremap, compat_sys_sysctl, sys32_getsid, sys_fdatasync, sys_nis_syscall
|
||||
/*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
|
||||
.word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys_setxattr
|
||||
/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents
|
||||
.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
|
||||
/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
|
||||
.word sys_setpgid, sys_fremovexattr, sys_tkill, sparc_exit_group, sys_newuname
|
||||
/*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
|
||||
.word sys_epoll_wait, sys_ioprio_set, sys_getppid, compat_sys_sparc_sigaction, sys_sgetmask
|
||||
/*200*/ .word sys_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
|
||||
.word sys32_readahead, sys32_socketcall, sys_syslog, sys32_lookup_dcookie, sys32_fadvise64
|
||||
/*210*/ .word sys32_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, compat_sys_sysinfo
|
||||
.word compat_sys_ipc, sys32_sigreturn, sys_clone, sys_ioprio_get, compat_sys_adjtimex
|
||||
/*220*/ .word compat_sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
|
||||
.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
|
||||
/*230*/ .word sys32_select, compat_sys_time, sys_splice, compat_sys_stime, compat_sys_statfs64
|
||||
.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
|
||||
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
|
||||
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, compat_sys_sched_rr_get_interval, compat_sys_nanosleep
|
||||
/*250*/ .word sys_mremap, compat_sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall
|
||||
.word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
|
||||
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
|
||||
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
|
||||
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
|
||||
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
|
||||
/*280*/ .word sys32_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat
|
||||
/*280*/ .word sys_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat
|
||||
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
|
||||
/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
|
||||
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
|
||||
|
Reference in New Issue
Block a user