diff options
Diffstat (limited to 'arch/mips/kernel/signal_n32.c')
-rw-r--r-- | arch/mips/kernel/signal_n32.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index ec61b2670ba6..3e168c08a3a8 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #define __NR_N32_rt_sigreturn 6211 | 48 | #define __NR_N32_rt_sigreturn 6211 |
49 | #define __NR_N32_restart_syscall 6214 | 49 | #define __NR_N32_restart_syscall 6214 |
50 | 50 | ||
51 | #define DEBUG_SIG 0 | ||
52 | |||
51 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 53 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
52 | 54 | ||
53 | /* IRIX compatible stack_t */ | 55 | /* IRIX compatible stack_t */ |
@@ -79,16 +81,49 @@ struct rt_sigframe_n32 { | |||
79 | #endif | 81 | #endif |
80 | }; | 82 | }; |
81 | 83 | ||
84 | extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat); | ||
85 | |||
86 | save_static_function(sysn32_rt_sigsuspend); | ||
87 | __attribute_used__ noinline static int | ||
88 | _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | ||
89 | { | ||
90 | compat_sigset_t __user *unewset, uset; | ||
91 | size_t sigsetsize; | ||
92 | sigset_t newset; | ||
93 | |||
94 | /* XXX Don't preclude handling different sized sigset_t's. */ | ||
95 | sigsetsize = regs.regs[5]; | ||
96 | if (sigsetsize != sizeof(sigset_t)) | ||
97 | return -EINVAL; | ||
98 | |||
99 | unewset = (compat_sigset_t __user *) regs.regs[4]; | ||
100 | if (copy_from_user(&uset, unewset, sizeof(uset))) | ||
101 | return -EFAULT; | ||
102 | sigset_from_compat (&newset, &uset); | ||
103 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
104 | |||
105 | spin_lock_irq(¤t->sighand->siglock); | ||
106 | current->saved_sigmask = current->blocked; | ||
107 | current->blocked = newset; | ||
108 | recalc_sigpending(); | ||
109 | spin_unlock_irq(¤t->sighand->siglock); | ||
110 | |||
111 | current->state = TASK_INTERRUPTIBLE; | ||
112 | schedule(); | ||
113 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
114 | return -ERESTARTNOHAND; | ||
115 | } | ||
116 | |||
82 | save_static_function(sysn32_rt_sigreturn); | 117 | save_static_function(sysn32_rt_sigreturn); |
83 | __attribute_used__ noinline static void | 118 | __attribute_used__ noinline static void |
84 | _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | 119 | _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
85 | { | 120 | { |
86 | struct rt_sigframe_n32 *frame; | 121 | struct rt_sigframe_n32 __user *frame; |
87 | sigset_t set; | 122 | sigset_t set; |
88 | stack_t st; | 123 | stack_t st; |
89 | s32 sp; | 124 | s32 sp; |
90 | 125 | ||
91 | frame = (struct rt_sigframe_n32 *) regs.regs[29]; | 126 | frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; |
92 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 127 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
93 | goto badframe; | 128 | goto badframe; |
94 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) | 129 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) |
@@ -106,7 +141,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
106 | /* The ucontext contains a stack32_t, so we must convert! */ | 141 | /* The ucontext contains a stack32_t, so we must convert! */ |
107 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 142 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
108 | goto badframe; | 143 | goto badframe; |
109 | st.ss_size = (long) sp; | 144 | st.ss_sp = (void *)(long) sp; |
110 | if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) | 145 | if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) |
111 | goto badframe; | 146 | goto badframe; |
112 | if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) | 147 | if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) |
@@ -114,7 +149,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
114 | 149 | ||
115 | /* It is more difficult to avoid calling this function than to | 150 | /* It is more difficult to avoid calling this function than to |
116 | call it and ignore errors. */ | 151 | call it and ignore errors. */ |
117 | do_sigaltstack(&st, NULL, regs.regs[29]); | 152 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); |
118 | 153 | ||
119 | /* | 154 | /* |
120 | * Don't let your children do this ... | 155 | * Don't let your children do this ... |
@@ -133,7 +168,7 @@ badframe: | |||
133 | int setup_rt_frame_n32(struct k_sigaction * ka, | 168 | int setup_rt_frame_n32(struct k_sigaction * ka, |
134 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) | 169 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) |
135 | { | 170 | { |
136 | struct rt_sigframe_n32 *frame; | 171 | struct rt_sigframe_n32 __user *frame; |
137 | int err = 0; | 172 | int err = 0; |
138 | s32 sp; | 173 | s32 sp; |
139 | 174 | ||
@@ -184,9 +219,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka, | |||
184 | current->comm, current->pid, | 219 | current->comm, current->pid, |
185 | frame, regs->cp0_epc, regs->regs[31]); | 220 | frame, regs->cp0_epc, regs->regs[31]); |
186 | #endif | 221 | #endif |
187 | return 1; | 222 | return 0; |
188 | 223 | ||
189 | give_sigsegv: | 224 | give_sigsegv: |
190 | force_sigsegv(signr, current); | 225 | force_sigsegv(signr, current); |
191 | return 0; | 226 | return -EFAULT; |
192 | } | 227 | } |