summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2008-01-11 20:44:17 +0100
committerChris Zankel <chris@zankel.net>2008-02-14 02:42:31 +0100
commit44c64e6b15ceab6a4927f54e1081a74ba096b95a (patch)
treefc96c7ddee6fa82655ada03f9f0ba2e9badf3d32 /arch
parent[XTENSA] Add support for configurable registers and coprocessors (diff)
downloadlinux-44c64e6b15ceab6a4927f54e1081a74ba096b95a.tar.xz
linux-44c64e6b15ceab6a4927f54e1081a74ba096b95a.zip
[XTENSA] Add support for the sa_restorer function
Supporting the sa_restorer function allows for better security since the sigreturn system call doesn't need to be placed on the stack, so the stack doesn't need to be executable. This requires support from the c-library as it has to provide the restorer function. Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/xtensa/kernel/signal.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 299be42d116b..f2220b5bdce6 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -381,14 +381,19 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(frame, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- /* Create sys_rt_sigreturn syscall in stack frame */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ ra = (unsigned long)ka->sa.sa_restorer;
+ } else {
- err |= gen_return_code(frame->retcode);
+ /* Create sys_rt_sigreturn syscall in stack frame */
- if (err) {
- goto give_sigsegv;
+ err |= gen_return_code(frame->retcode);
+
+ if (err) {
+ goto give_sigsegv;
+ }
+ ra = (unsigned long) frame->retcode;
}
-
/*
* Create signal handler execution context.
@@ -402,7 +407,6 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up a stack frame for a call4
* Note: PS.CALLINC is set to one by start_thread
*/
- ra = (unsigned long) frame->retcode;
regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
regs->areg[6] = (unsigned long) signal;
regs->areg[7] = (unsigned long) &frame->info;