Commit b0baa0f5 authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: fix setting of interrupted syscall return value

From: Bodo Stroesser <bstroesser@fujitsu-siemens.com>

handle_signal now checks whether it is being called from a system call
invocation.
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 677913b6
...@@ -44,45 +44,37 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -44,45 +44,37 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
{ {
void (*restorer)(void); void (*restorer)(void);
unsigned long sp; unsigned long sp;
int err, error, ret; int err;
error = PT_REGS_SYSCALL_RET(&current->thread.regs);
ret = 0;
/* Always make any pending restarted system calls return -EINTR */ /* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall; current_thread_info()->restart_block.fn = do_no_restart_syscall;
switch(error){
/* Did we come from a system call? */
if(PT_REGS_SYSCALL_NR(regs) >= 0){
/* If so, check system call restarting.. */
switch(PT_REGS_SYSCALL_RET(regs)){
case -ERESTART_RESTARTBLOCK: case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
ret = -EINTR; PT_REGS_SYSCALL_RET(regs) = -EINTR;
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ka->sa.sa_flags & SA_RESTART)) {
ret = -EINTR; PT_REGS_SYSCALL_RET(regs) = -EINTR;
break; break;
} }
/* fallthrough */ /* fallthrough */
case -ERESTARTNOINTR: case -ERESTARTNOINTR:
PT_REGS_RESTART_SYSCALL(regs); PT_REGS_RESTART_SYSCALL(regs);
PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
/* This is because of the UM_SET_SYSCALL_RETURN and the fact
* that on i386 the system call number and return value are
* in the same register. When the system call restarts, %eax
* had better have the system call number in it. Since the
* return value doesn't matter (except that it shouldn't be
* -ERESTART*), we'll stick the system call number there.
*/
ret = PT_REGS_SYSCALL_NR(regs);
break; break;
} }
}
sp = PT_REGS_SP(regs); sp = PT_REGS_SP(regs);
if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size; sp = current->sas_ss_sp + current->sas_ss_size;
if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);
if (ka->sa.sa_flags & SA_RESTORER) if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer; restorer = ka->sa.sa_restorer;
else restorer = NULL; else restorer = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment