diff options
Diffstat (limited to 'arch/s390/kernel/signal.c')
-rw-r--r-- | arch/s390/kernel/signal.c | 78 |
1 files changed, 32 insertions, 46 deletions
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 42b49f9e19bf..469c4c6d9182 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
200 | frame = get_sigframe(ka, regs, sizeof(sigframe)); | 200 | frame = get_sigframe(ka, regs, sizeof(sigframe)); |
201 | 201 | ||
202 | if (frame == (void __user *) -1UL) | 202 | if (frame == (void __user *) -1UL) |
203 | goto give_sigsegv; | 203 | return -EFAULT; |
204 | 204 | ||
205 | if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE)) | 205 | if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE)) |
206 | goto give_sigsegv; | 206 | return -EFAULT; |
207 | 207 | ||
208 | if (save_sigregs(regs, &frame->sregs)) | 208 | if (save_sigregs(regs, &frame->sregs)) |
209 | goto give_sigsegv; | 209 | return -EFAULT; |
210 | if (__put_user(&frame->sregs, &frame->sc.sregs)) | 210 | if (__put_user(&frame->sregs, &frame->sc.sregs)) |
211 | goto give_sigsegv; | 211 | return -EFAULT; |
212 | 212 | ||
213 | /* Set up to return from userspace. If provided, use a stub | 213 | /* Set up to return from userspace. If provided, use a stub |
214 | already in userspace. */ | 214 | already in userspace. */ |
@@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
220 | frame->retcode | PSW_ADDR_AMODE; | 220 | frame->retcode | PSW_ADDR_AMODE; |
221 | if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, | 221 | if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, |
222 | (u16 __user *)(frame->retcode))) | 222 | (u16 __user *)(frame->retcode))) |
223 | goto give_sigsegv; | 223 | return -EFAULT; |
224 | } | 224 | } |
225 | 225 | ||
226 | /* Set up backchain. */ | 226 | /* Set up backchain. */ |
227 | if (__put_user(regs->gprs[15], (addr_t __user *) frame)) | 227 | if (__put_user(regs->gprs[15], (addr_t __user *) frame)) |
228 | goto give_sigsegv; | 228 | return -EFAULT; |
229 | 229 | ||
230 | /* Set up registers for signal handler */ | 230 | /* Set up registers for signal handler */ |
231 | regs->gprs[15] = (unsigned long) frame; | 231 | regs->gprs[15] = (unsigned long) frame; |
@@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
250 | 250 | ||
251 | /* Place signal number on stack to allow backtrace from handler. */ | 251 | /* Place signal number on stack to allow backtrace from handler. */ |
252 | if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) | 252 | if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) |
253 | goto give_sigsegv; | 253 | return -EFAULT; |
254 | return 0; | 254 | return 0; |
255 | |||
256 | give_sigsegv: | ||
257 | force_sigsegv(sig, current); | ||
258 | return -EFAULT; | ||
259 | } | 255 | } |
260 | 256 | ||
261 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 257 | static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, |
262 | sigset_t *set, struct pt_regs * regs) | 258 | struct pt_regs *regs) |
263 | { | 259 | { |
264 | int err = 0; | 260 | int err = 0; |
265 | rt_sigframe __user *frame; | 261 | rt_sigframe __user *frame; |
266 | 262 | ||
267 | frame = get_sigframe(ka, regs, sizeof(rt_sigframe)); | 263 | frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe)); |
268 | 264 | ||
269 | if (frame == (void __user *) -1UL) | 265 | if (frame == (void __user *) -1UL) |
270 | goto give_sigsegv; | 266 | return -EFAULT; |
271 | 267 | ||
272 | if (copy_siginfo_to_user(&frame->info, info)) | 268 | if (copy_siginfo_to_user(&frame->info, &ksig->info)) |
273 | goto give_sigsegv; | 269 | return -EFAULT; |
274 | 270 | ||
275 | /* Create the ucontext. */ | 271 | /* Create the ucontext. */ |
276 | err |= __put_user(0, &frame->uc.uc_flags); | 272 | err |= __put_user(0, &frame->uc.uc_flags); |
@@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
279 | err |= save_sigregs(regs, &frame->uc.uc_mcontext); | 275 | err |= save_sigregs(regs, &frame->uc.uc_mcontext); |
280 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 276 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
281 | if (err) | 277 | if (err) |
282 | goto give_sigsegv; | 278 | return -EFAULT; |
283 | 279 | ||
284 | /* Set up to return from userspace. If provided, use a stub | 280 | /* Set up to return from userspace. If provided, use a stub |
285 | already in userspace. */ | 281 | already in userspace. */ |
286 | if (ka->sa.sa_flags & SA_RESTORER) { | 282 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
287 | regs->gprs[14] = (unsigned long) | 283 | regs->gprs[14] = (unsigned long) |
288 | ka->sa.sa_restorer | PSW_ADDR_AMODE; | 284 | ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE; |
289 | } else { | 285 | } else { |
290 | regs->gprs[14] = (unsigned long) | 286 | regs->gprs[14] = (unsigned long) |
291 | frame->retcode | PSW_ADDR_AMODE; | 287 | frame->retcode | PSW_ADDR_AMODE; |
292 | if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, | 288 | if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, |
293 | (u16 __user *)(frame->retcode))) | 289 | (u16 __user *)(frame->retcode))) |
294 | goto give_sigsegv; | 290 | return -EFAULT; |
295 | } | 291 | } |
296 | 292 | ||
297 | /* Set up backchain. */ | 293 | /* Set up backchain. */ |
298 | if (__put_user(regs->gprs[15], (addr_t __user *) frame)) | 294 | if (__put_user(regs->gprs[15], (addr_t __user *) frame)) |
299 | goto give_sigsegv; | 295 | return -EFAULT; |
300 | 296 | ||
301 | /* Set up registers for signal handler */ | 297 | /* Set up registers for signal handler */ |
302 | regs->gprs[15] = (unsigned long) frame; | 298 | regs->gprs[15] = (unsigned long) frame; |
@@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
304 | regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | | 300 | regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | |
305 | (PSW_USER_BITS & PSW_MASK_ASC) | | 301 | (PSW_USER_BITS & PSW_MASK_ASC) | |
306 | (regs->psw.mask & ~PSW_MASK_ASC); | 302 | (regs->psw.mask & ~PSW_MASK_ASC); |
307 | regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; | 303 | regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE; |
308 | 304 | ||
309 | regs->gprs[2] = map_signal(sig); | 305 | regs->gprs[2] = map_signal(ksig->sig); |
310 | regs->gprs[3] = (unsigned long) &frame->info; | 306 | regs->gprs[3] = (unsigned long) &frame->info; |
311 | regs->gprs[4] = (unsigned long) &frame->uc; | 307 | regs->gprs[4] = (unsigned long) &frame->uc; |
312 | regs->gprs[5] = task_thread_info(current)->last_break; | 308 | regs->gprs[5] = task_thread_info(current)->last_break; |
313 | return 0; | 309 | return 0; |
314 | |||
315 | give_sigsegv: | ||
316 | force_sigsegv(sig, current); | ||
317 | return -EFAULT; | ||
318 | } | 310 | } |
319 | 311 | ||
320 | static void handle_signal(unsigned long sig, struct k_sigaction *ka, | 312 | static void handle_signal(struct ksignal *ksig, sigset_t *oldset, |
321 | siginfo_t *info, sigset_t *oldset, | 313 | struct pt_regs *regs) |
322 | struct pt_regs *regs) | ||
323 | { | 314 | { |
324 | int ret; | 315 | int ret; |
325 | 316 | ||
326 | /* Set up the stack frame */ | 317 | /* Set up the stack frame */ |
327 | if (ka->sa.sa_flags & SA_SIGINFO) | 318 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
328 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 319 | ret = setup_rt_frame(ksig, oldset, regs); |
329 | else | 320 | else |
330 | ret = setup_frame(sig, ka, oldset, regs); | 321 | ret = setup_frame(ksig->sig, &ksig->ka, oldset, regs); |
331 | if (ret) | 322 | |
332 | return; | 323 | signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP)); |
333 | signal_delivered(sig, info, ka, regs, | ||
334 | test_thread_flag(TIF_SINGLE_STEP)); | ||
335 | } | 324 | } |
336 | 325 | ||
337 | /* | 326 | /* |
@@ -345,9 +334,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
345 | */ | 334 | */ |
346 | void do_signal(struct pt_regs *regs) | 335 | void do_signal(struct pt_regs *regs) |
347 | { | 336 | { |
348 | siginfo_t info; | 337 | struct ksignal ksig; |
349 | int signr; | ||
350 | struct k_sigaction ka; | ||
351 | sigset_t *oldset = sigmask_to_save(); | 338 | sigset_t *oldset = sigmask_to_save(); |
352 | 339 | ||
353 | /* | 340 | /* |
@@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs) | |||
357 | */ | 344 | */ |
358 | current_thread_info()->system_call = | 345 | current_thread_info()->system_call = |
359 | test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0; | 346 | test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0; |
360 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
361 | 347 | ||
362 | if (signr > 0) { | 348 | if (get_signal(&ksig)) { |
363 | /* Whee! Actually deliver the signal. */ | 349 | /* Whee! Actually deliver the signal. */ |
364 | if (current_thread_info()->system_call) { | 350 | if (current_thread_info()->system_call) { |
365 | regs->int_code = current_thread_info()->system_call; | 351 | regs->int_code = current_thread_info()->system_call; |
@@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs) | |||
370 | regs->gprs[2] = -EINTR; | 356 | regs->gprs[2] = -EINTR; |
371 | break; | 357 | break; |
372 | case -ERESTARTSYS: | 358 | case -ERESTARTSYS: |
373 | if (!(ka.sa.sa_flags & SA_RESTART)) { | 359 | if (!(ksig.ka.sa.sa_flags & SA_RESTART)) { |
374 | regs->gprs[2] = -EINTR; | 360 | regs->gprs[2] = -EINTR; |
375 | break; | 361 | break; |
376 | } | 362 | } |
@@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs) | |||
387 | clear_pt_regs_flag(regs, PIF_SYSCALL); | 373 | clear_pt_regs_flag(regs, PIF_SYSCALL); |
388 | 374 | ||
389 | if (is_compat_task()) | 375 | if (is_compat_task()) |
390 | handle_signal32(signr, &ka, &info, oldset, regs); | 376 | handle_signal32(&ksig, oldset, regs); |
391 | else | 377 | else |
392 | handle_signal(signr, &ka, &info, oldset, regs); | 378 | handle_signal(&ksig, oldset, regs); |
393 | return; | 379 | return; |
394 | } | 380 | } |
395 | 381 | ||