From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Vrabel Subject: Re: [PATCH] xen/x86: don't corrupt %eip when returning from a signal handler Date: Wed, 17 Oct 2012 12:48:36 +0100 Message-ID: <507E9B14.1040601@citrix.com> References: <1350474150-3990-1-git-send-email-david.vrabel@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1350474150-3990-1-git-send-email-david.vrabel@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: David Vrabel Cc: Frediano Ziglio , Konrad Rzeszutek Wilk , "stable@kernel.org" , "xen-devel@lists.xen.org" List-Id: xen-devel@lists.xenproject.org On 17/10/12 12:42, David Vrabel wrote: > From: David Vrabel > > In 32 bit guests, if a userspace process has %eax == -ERESTARTSYS > (-512) or -ERESTARTNOINTR (-513) when it is interrupted by an event > /and/ the process has a pending signal then %eip (and %eax) are > corrupted when returning to the main process after handling the > signal. The application may then crash with SIGSEGV or a SIGILL or it > may have subtly incorrect behaviour (depending on what instruction it > returned to). The following test program shows the bug. It will receive the signal when in the infinite loop and return to the preceeding int 3 instruction. Big thanks to Frediano for producing the test program and the majority of the effort in tracking down this bug. David 8<-------------------------- #include #include #include #include #include static void handler(int sig) { static unsigned count = 0; if (++count == 60 * 1000) exit(0); } int main(void) { struct sigaction act; // set signal sigfillset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = handler; int err = sigaction(SIGALRM, &act, NULL); assert(!err); // set timer struct itimerval ival = { { 0, 1000 }, { 0, 1000 } }; err = setitimer(ITIMER_REAL, &ival, NULL); assert(!err); #if !defined(__x86_64__) && !defined(__i386__) # error This code work only on Intel architecture! #endif // wait for a core !! asm( #ifdef __x86_64__ " mov $-513, %rax\n" #else " mov $-513, %eax\n" #endif " jmp infinite\n" " int $3\n" " int $3\n" " int $3\n" " int $3\n" "infinite:\n" " jmp infinite\n" ); return 0; }