From: Alin Jula <alin.jula@sap.com>
To: linux-kernel@vger.kernel.org
Cc: alin.jula@sap.com
Subject: sigaction with SA_SIGINFO does not pass the correct return context
Date: Wed, 03 Sep 2008 10:26:51 -0700 [thread overview]
Message-ID: <1220462811.3541.18.camel@linux-6ir4.site> (raw)
Summary: sigaction with SG_SIGINFO passes the incorrect context on
OpenSuse (kernels 2.6.16.21-0.8-smp and 2.6.25.11-0.1-default).
However, it passes the correct one on Ubuntu (kernel
2.6.24-19-generic).
I'm trying to catch the SIGSEGV signal, do something, and then return
control back to the application. I use "sigaction" with the SA_SIGINFO
flag. This flags allows a handler to be called upon a signal, and it
should (POSIX defined) also provide the context of the thread when the
signal was issued. The problem is that the right context does _not_ work
on OpenSuse, but it works on Ubuntu.
So I was wondering if there is a specific action that one needs to take
on OpenSuse when dealing with this issue, or if there is a bug in the
kernel/opensuse ?
On Ubuntu (kernel 2.6.24-19-generic), sigaction correctly provides the
context of the thread that raised the signal. However, on two other
installations of OpenSuse (kernels 2.6.16.21-0.8-smp and
2.6.25.11-0.1-default), sigaction provides a different context.
Below is the code example, with its summary. 4KB get allocated with
mmap, with "not to be accessed" protection. A write to this memory chunk
raises a SIGSEGV signal. This signal is then caught, and the memory
protection is changed to read+write. Then, the control is given back to
the instruction that raised this signal, and the application should
proceed from there. The code works on Ubuntu, but on the both OpenSuse
installations that I tried (see above for kernels), the context passed
by sigaction is the context of the handler instead of the instruction
that raised the signal.
Here is the code:
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <ucontext.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
ucontext_t context_trigger, context_sig;
struct sigaction sa_new, sa_old;
static void
handler(int sig, siginfo_t *si, void *context)
{
if ((sig == SIGSEGV) || (sig == SIGBUS) )
{
printf("\nGot SIGSEGV or SIGBUS at address: 0x%lx and context
=%lx\n",(long) si->si_addr, context);
if (mprotect(si->si_addr, 4096 ,PROT_READ | PROT_WRITE) == -1)
handle_error("mprotect failed from the handler");
else
printf("\nmprotect set the protection to RW\n");
#if 1
// The intention here is to switch back to the context that signaled
the SIGSEGV. Unfortunately, it does not
// do that. Instead, it switches the context back to the handler
function, in a recursive call.
swapcontext(&context_sig, (ucontext_t*)context);
#else
// Manually set the context to the point previous to accessing the
memory. This works !
swapcontext(&context_sig, &context_trigger);
#endif
}
}
int
main(int argc, char *argv[])
{
/* Set the handler */
sa_new.sa_flags = SA_SIGINFO;
sigemptyset(&sa_new.sa_mask);
sa_new.sa_sigaction = handler;
if (sigaction(SIGSEGV, &sa_new, &sa_old) == -1)
handle_error("sigaction");
/* Allocate 4096 bytes with initial protection PROT_NONE */
char* p = (char*)mmap(0,4096,PROT_NONE, MAP_ANONYMOUS |
MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
handle_error("mmap");
getcontext(&context_trigger);
/* Access the protected memory, which will raise a SIGSEGV or SIGBUS
*/
*(p) = 'a';
printf("\nSuccess\n");
exit(EXIT_SUCCESS);
}
Any help/pointer would be greatly appreciated.
Thanks,
Alin Jula
next reply other threads:[~2008-09-04 4:55 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-03 17:26 Alin Jula [this message]
2008-09-04 7:33 ` Mikael Pettersson
2008-09-05 20:49 ` Alin Jula
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1220462811.3541.18.camel@linux-6ir4.site \
--to=alin.jula@sap.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome