diff options
Diffstat (limited to 'arch/arm64/kernel/signal.c')
-rw-r--r-- | arch/arm64/kernel/signal.c | 58 |
1 files changed, 22 insertions, 36 deletions
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 6357b9c6c90e..6fa792137eda 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c | |||
@@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigframe __user *sf, | |||
209 | return err; | 209 | return err; |
210 | } | 210 | } |
211 | 211 | ||
212 | static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka, | 212 | static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig, |
213 | struct pt_regs *regs) | 213 | struct pt_regs *regs) |
214 | { | 214 | { |
215 | unsigned long sp, sp_top; | 215 | unsigned long sp, sp_top; |
216 | struct rt_sigframe __user *frame; | 216 | struct rt_sigframe __user *frame; |
217 | 217 | ||
218 | sp = sp_top = regs->sp; | 218 | sp = sp_top = sigsp(regs->sp, ksig); |
219 | |||
220 | /* | ||
221 | * This is the X/Open sanctioned signal stack switching. | ||
222 | */ | ||
223 | if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) | ||
224 | sp = sp_top = current->sas_ss_sp + current->sas_ss_size; | ||
225 | 219 | ||
226 | sp = (sp - sizeof(struct rt_sigframe)) & ~15; | 220 | sp = (sp - sizeof(struct rt_sigframe)) & ~15; |
227 | frame = (struct rt_sigframe __user *)sp; | 221 | frame = (struct rt_sigframe __user *)sp; |
@@ -253,13 +247,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
253 | regs->regs[30] = (unsigned long)sigtramp; | 247 | regs->regs[30] = (unsigned long)sigtramp; |
254 | } | 248 | } |
255 | 249 | ||
256 | static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | 250 | static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, |
257 | sigset_t *set, struct pt_regs *regs) | 251 | struct pt_regs *regs) |
258 | { | 252 | { |
259 | struct rt_sigframe __user *frame; | 253 | struct rt_sigframe __user *frame; |
260 | int err = 0; | 254 | int err = 0; |
261 | 255 | ||
262 | frame = get_sigframe(ka, regs); | 256 | frame = get_sigframe(ksig, regs); |
263 | if (!frame) | 257 | if (!frame) |
264 | return 1; | 258 | return 1; |
265 | 259 | ||
@@ -269,9 +263,9 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | |||
269 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); | 263 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); |
270 | err |= setup_sigframe(frame, regs, set); | 264 | err |= setup_sigframe(frame, regs, set); |
271 | if (err == 0) { | 265 | if (err == 0) { |
272 | setup_return(regs, ka, frame, usig); | 266 | setup_return(regs, &ksig->ka, frame, usig); |
273 | if (ka->sa.sa_flags & SA_SIGINFO) { | 267 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
274 | err |= copy_siginfo_to_user(&frame->info, info); | 268 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
275 | regs->regs[1] = (unsigned long)&frame->info; | 269 | regs->regs[1] = (unsigned long)&frame->info; |
276 | regs->regs[2] = (unsigned long)&frame->uc; | 270 | regs->regs[2] = (unsigned long)&frame->uc; |
277 | } | 271 | } |
@@ -291,13 +285,12 @@ static void setup_restart_syscall(struct pt_regs *regs) | |||
291 | /* | 285 | /* |
292 | * OK, we're invoking a handler | 286 | * OK, we're invoking a handler |
293 | */ | 287 | */ |
294 | static void handle_signal(unsigned long sig, struct k_sigaction *ka, | 288 | static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
295 | siginfo_t *info, struct pt_regs *regs) | ||
296 | { | 289 | { |
297 | struct thread_info *thread = current_thread_info(); | 290 | struct thread_info *thread = current_thread_info(); |
298 | struct task_struct *tsk = current; | 291 | struct task_struct *tsk = current; |
299 | sigset_t *oldset = sigmask_to_save(); | 292 | sigset_t *oldset = sigmask_to_save(); |
300 | int usig = sig; | 293 | int usig = ksig->sig; |
301 | int ret; | 294 | int ret; |
302 | 295 | ||
303 | /* | 296 | /* |
@@ -310,13 +303,12 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
310 | * Set up the stack frame | 303 | * Set up the stack frame |
311 | */ | 304 | */ |
312 | if (is_compat_task()) { | 305 | if (is_compat_task()) { |
313 | if (ka->sa.sa_flags & SA_SIGINFO) | 306 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
314 | ret = compat_setup_rt_frame(usig, ka, info, oldset, | 307 | ret = compat_setup_rt_frame(usig, ksig, oldset, regs); |
315 | regs); | ||
316 | else | 308 | else |
317 | ret = compat_setup_frame(usig, ka, oldset, regs); | 309 | ret = compat_setup_frame(usig, ksig, oldset, regs); |
318 | } else { | 310 | } else { |
319 | ret = setup_rt_frame(usig, ka, info, oldset, regs); | 311 | ret = setup_rt_frame(usig, ksig, oldset, regs); |
320 | } | 312 | } |
321 | 313 | ||
322 | /* | 314 | /* |
@@ -324,18 +316,14 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
324 | */ | 316 | */ |
325 | ret |= !valid_user_regs(®s->user_regs); | 317 | ret |= !valid_user_regs(®s->user_regs); |
326 | 318 | ||
327 | if (ret != 0) { | ||
328 | force_sigsegv(sig, tsk); | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | /* | 319 | /* |
333 | * Fast forward the stepping logic so we step into the signal | 320 | * Fast forward the stepping logic so we step into the signal |
334 | * handler. | 321 | * handler. |
335 | */ | 322 | */ |
336 | user_fastforward_single_step(tsk); | 323 | if (!ret) |
324 | user_fastforward_single_step(tsk); | ||
337 | 325 | ||
338 | signal_delivered(sig, info, ka, regs, 0); | 326 | signal_setup_done(ret, ksig, 0); |
339 | } | 327 | } |
340 | 328 | ||
341 | /* | 329 | /* |
@@ -350,10 +338,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
350 | static void do_signal(struct pt_regs *regs) | 338 | static void do_signal(struct pt_regs *regs) |
351 | { | 339 | { |
352 | unsigned long continue_addr = 0, restart_addr = 0; | 340 | unsigned long continue_addr = 0, restart_addr = 0; |
353 | struct k_sigaction ka; | 341 | int retval = 0; |
354 | siginfo_t info; | ||
355 | int signr, retval = 0; | ||
356 | int syscall = (int)regs->syscallno; | 342 | int syscall = (int)regs->syscallno; |
343 | struct ksignal ksig; | ||
357 | 344 | ||
358 | /* | 345 | /* |
359 | * If we were from a system call, check for system call restarting... | 346 | * If we were from a system call, check for system call restarting... |
@@ -387,8 +374,7 @@ static void do_signal(struct pt_regs *regs) | |||
387 | * Get the signal to deliver. When running under ptrace, at this point | 374 | * Get the signal to deliver. When running under ptrace, at this point |
388 | * the debugger may change all of our registers. | 375 | * the debugger may change all of our registers. |
389 | */ | 376 | */ |
390 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 377 | if (get_signal(&ksig)) { |
391 | if (signr > 0) { | ||
392 | /* | 378 | /* |
393 | * Depending on the signal settings, we may need to revert the | 379 | * Depending on the signal settings, we may need to revert the |
394 | * decision to restart the system call, but skip this if a | 380 | * decision to restart the system call, but skip this if a |
@@ -398,12 +384,12 @@ static void do_signal(struct pt_regs *regs) | |||
398 | (retval == -ERESTARTNOHAND || | 384 | (retval == -ERESTARTNOHAND || |
399 | retval == -ERESTART_RESTARTBLOCK || | 385 | retval == -ERESTART_RESTARTBLOCK || |
400 | (retval == -ERESTARTSYS && | 386 | (retval == -ERESTARTSYS && |
401 | !(ka.sa.sa_flags & SA_RESTART)))) { | 387 | !(ksig.ka.sa.sa_flags & SA_RESTART)))) { |
402 | regs->regs[0] = -EINTR; | 388 | regs->regs[0] = -EINTR; |
403 | regs->pc = continue_addr; | 389 | regs->pc = continue_addr; |
404 | } | 390 | } |
405 | 391 | ||
406 | handle_signal(signr, &ka, &info, regs); | 392 | handle_signal(&ksig, regs); |
407 | return; | 393 | return; |
408 | } | 394 | } |
409 | 395 | ||