diff options
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/ptrace.c | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/signal_64.c | 38 | 
2 files changed, 41 insertions, 6 deletions
| diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 8f64abe699fd..d5904eef1d31 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -1055,10 +1055,17 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value) | |||
| 1055 | R32(esi, si); | 1055 | R32(esi, si); | 
| 1056 | R32(ebp, bp); | 1056 | R32(ebp, bp); | 
| 1057 | R32(eax, ax); | 1057 | R32(eax, ax); | 
| 1058 | R32(orig_eax, orig_ax); | ||
| 1059 | R32(eip, ip); | 1058 | R32(eip, ip); | 
| 1060 | R32(esp, sp); | 1059 | R32(esp, sp); | 
| 1061 | 1060 | ||
| 1061 | case offsetof(struct user32, regs.orig_eax): | ||
| 1062 | /* | ||
| 1063 | * Sign-extend the value so that orig_eax = -1 | ||
| 1064 | * causes (long)orig_ax < 0 tests to fire correctly. | ||
| 1065 | */ | ||
| 1066 | regs->orig_ax = (long) (s32) value; | ||
| 1067 | break; | ||
| 1068 | |||
| 1062 | case offsetof(struct user32, regs.eflags): | 1069 | case offsetof(struct user32, regs.eflags): | 
| 1063 | return set_flags(child, value); | 1070 | return set_flags(child, value); | 
| 1064 | 1071 | ||
| diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 56b72fb67f9b..1c83e5124c65 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
| @@ -311,6 +311,35 @@ give_sigsegv: | |||
| 311 | } | 311 | } | 
| 312 | 312 | ||
| 313 | /* | 313 | /* | 
| 314 | * Return -1L or the syscall number that @regs is executing. | ||
| 315 | */ | ||
| 316 | static long current_syscall(struct pt_regs *regs) | ||
| 317 | { | ||
| 318 | /* | ||
| 319 | * We always sign-extend a -1 value being set here, | ||
| 320 | * so this is always either -1L or a syscall number. | ||
| 321 | */ | ||
| 322 | return regs->orig_ax; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* | ||
| 326 | * Return a value that is -EFOO if the system call in @regs->orig_ax | ||
| 327 | * returned an error. This only works for @regs from @current. | ||
| 328 | */ | ||
| 329 | static long current_syscall_ret(struct pt_regs *regs) | ||
| 330 | { | ||
| 331 | #ifdef CONFIG_IA32_EMULATION | ||
| 332 | if (test_thread_flag(TIF_IA32)) | ||
| 333 | /* | ||
| 334 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO | ||
| 335 | * and will match correctly in comparisons. | ||
| 336 | */ | ||
| 337 | return (int) regs->ax; | ||
| 338 | #endif | ||
| 339 | return regs->ax; | ||
| 340 | } | ||
| 341 | |||
| 342 | /* | ||
| 314 | * OK, we're invoking a handler | 343 | * OK, we're invoking a handler | 
| 315 | */ | 344 | */ | 
| 316 | 345 | ||
| @@ -327,9 +356,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 327 | #endif | 356 | #endif | 
| 328 | 357 | ||
| 329 | /* Are we from a system call? */ | 358 | /* Are we from a system call? */ | 
| 330 | if ((long)regs->orig_ax >= 0) { | 359 | if (current_syscall(regs) >= 0) { | 
| 331 | /* If so, check system call restarting.. */ | 360 | /* If so, check system call restarting.. */ | 
| 332 | switch (regs->ax) { | 361 | switch (current_syscall_ret(regs)) { | 
| 333 | case -ERESTART_RESTARTBLOCK: | 362 | case -ERESTART_RESTARTBLOCK: | 
| 334 | case -ERESTARTNOHAND: | 363 | case -ERESTARTNOHAND: | 
| 335 | regs->ax = -EINTR; | 364 | regs->ax = -EINTR; | 
| @@ -426,10 +455,9 @@ static void do_signal(struct pt_regs *regs) | |||
| 426 | } | 455 | } | 
| 427 | 456 | ||
| 428 | /* Did we come from a system call? */ | 457 | /* Did we come from a system call? */ | 
| 429 | if ((long)regs->orig_ax >= 0) { | 458 | if (current_syscall(regs) >= 0) { | 
| 430 | /* Restart the system call - no handlers present */ | 459 | /* Restart the system call - no handlers present */ | 
| 431 | long res = regs->ax; | 460 | switch (current_syscall_ret(regs)) { | 
| 432 | switch (res) { | ||
| 433 | case -ERESTARTNOHAND: | 461 | case -ERESTARTNOHAND: | 
| 434 | case -ERESTARTSYS: | 462 | case -ERESTARTSYS: | 
| 435 | case -ERESTARTNOINTR: | 463 | case -ERESTARTNOINTR: | 
