uml: bad syscall restart handling
PATCH 1/1 uml: bad syscall restart handling
From: Bodo Stroesser <[email protected]>
The implementation of sys_sigreturn() and sys_rt_sigreturn() in UML differ from the ones in i386. In i386, orig_eax is set to -1. This is neccessary, since the return value of sys_*_sigreturn() is the value of eax in the thread, that was interrupted by the signal handler. If accidentaly eax contains -ERESTART_*, orig_eax *must* be -1 to avoid syscall restart processing in kern_do_signal(). If orig_eax is >=0, eip might be lowered by 2, the will fail. In UML PT_REGS_SYSCALL_NR() or UPT_SYSCALL_NR() have to be used instead of orig_eax.
While writing and testing an exploit for this, I saw that for most interrupts, the syscall number is undefined. So even on a return from interrupt a wrong syscall restart handling could happen.
And also: UML resumes a process with ptrace(PTRACE_SYSCALL/SYSEMU/SINGLESTEP when a syscall in UML in SKAS mode has been processed. But since there is a valid syscall number in the host's orig_eax, the host could do a wrong syscall restarting if the syscall in UML was a sigreturn() returning -ERESTART* To avoid this, in SKAS -1 should be written to regs.orig_eax before restore_registers().
---
arch/um/kernel/skas/process.c +3 -2
@@ -57,7 +57,7 @@ static void handle_trap(int pid, union u {int err, status; -UPT_SYSCALL_NR (regs) =PT_SYSCALL_NR (regs->skas.regs); +UPT_SYSCALL_NR (regs) =PT_SYSCALL_NR (regs->skas.regs);/* Mark this as a syscall */ if (!local_using_sysemu) {
@@ -156,6 +156,7 @@ void userspace(union uml_pt_regs *regs) regs->skas.is_user =1 ;save_registers (pid, regs); +UPT_SYSCALL_NR (regs) =-1 ;/* Assume: It's not a syscall */ if (WIFSTOPPED (status)){switch (WSTOPSIG (status)){
@@ -166,7 +167,6 @@ void userspace(union uml_pt_regs *regs)handle_trap (pid, regs, local_using_sysemu);break ;case SIGTRAP : -UPT_SYSCALL_NR (regs) =-1 ;relay_signal (SIGTRAP , regs);break ;case SIGIO :
@@ -182,6 +182,7 @@ void userspace(union uml_pt_regs *regs) "%d\n", WSTOPSIG(status)); }interrupt_end (); +PT_SYSCALL_NR (regs->skas.regs) =-1 ;/* Avoid -ERESTARTSYS handling in host */ }restore_registers (pid, regs);
arch/um/sys-i386/signal.c +2 -0
@@ -317,6 +317,7 @@ long sys_sigreturn(struct pt_regs regs)recalc_sigpending ();spin_unlock_irq (¤t->sighand->siglock);copy_sc_from_user (¤t->thread.regs, sc); +PT_REGS_SYSCALL_NR (¤t->thread.regs) =-1 ;/* Avoid ERESTART handling */ return (PT_REGS_SYSCALL_RET (¤t->thread.regs)); }
@@ -333,6 +334,7 @@ long sys_rt_sigreturn(struct pt_regs regrecalc_sigpending ();spin_unlock_irq (¤t->sighand->siglock);copy_sc_from_user (¤t->thread.regs, &uc->uc_mcontext); +PT_REGS_SYSCALL_NR (¤t->thread.regs) =-1 ;/* Avoid ERESTART handling */ return (PT_REGS_SYSCALL_RET (¤t->thread.regs)); }
arch/um/kernel/tt/tracer.c +2 -1
@@ -302,6 +302,8 @@ int tracer(int (*init_proc)(void *), voi task = cpu_tasks[proc_id].task; tracing =is_tracing (task); old_tracing = tracing; +if ( tracing )/* Assume: no syscall, when coming from user */ +do_sigtrap (task);switch (sig){case SIGUSR1 :
@@ -345,7 +347,6 @@ int tracer(int (*init_proc)(void *), voicontinue ; } tracing =0 ; -do_sigtrap (task);break ;case SIGPROF :if (tracing) sig =0 ;
-------------------------------------------------------
This Newsletter Sponsored by: Macrovision For reliable Linux application installations, use the industry's leading setup authoring tool, InstallShield X. Learn more and evaluate today. http://clk.atdmt.com/MSI/go/ins0030000001msi/direct/01/
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel