xtensa: fix signal delivery to FDPIC process
Fetch function descriptor pointed to by the signal handler pointer from
userspace on signal delivery and function pointer pointed to by the
sa_restorer on return from the signal handler.
Cc: stable@vger.kernel.org
Fixes: e3ddb8bbe0
("xtensa: add FDPIC and static PIE support for noMMU")
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
This commit is contained in:
parent
457391b038
commit
9c2cc74fb3
|
@ -343,7 +343,19 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
|||
struct rt_sigframe *frame;
|
||||
int err = 0, sig = ksig->sig;
|
||||
unsigned long sp, ra, tp, ps;
|
||||
unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
unsigned long handler_fdpic_GOT = 0;
|
||||
unsigned int base;
|
||||
bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
|
||||
(current->personality & FDPIC_FUNCPTRS);
|
||||
|
||||
if (fdpic) {
|
||||
unsigned long __user *fdpic_func_desc =
|
||||
(unsigned long __user *)handler;
|
||||
if (__get_user(handler, &fdpic_func_desc[0]) ||
|
||||
__get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
sp = regs->areg[1];
|
||||
|
||||
|
@ -373,20 +385,26 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
|||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
ra = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
if (fdpic) {
|
||||
unsigned long __user *fdpic_func_desc =
|
||||
(unsigned long __user *)ksig->ka.sa.sa_restorer;
|
||||
|
||||
err |= __get_user(ra, fdpic_func_desc);
|
||||
} else {
|
||||
ra = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Create sys_rt_sigreturn syscall in stack frame */
|
||||
|
||||
err |= gen_return_code(frame->retcode);
|
||||
|
||||
if (err) {
|
||||
return -EFAULT;
|
||||
}
|
||||
ra = (unsigned long) frame->retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Create signal handler execution context.
|
||||
* Return context not modified until this point.
|
||||
*/
|
||||
|
@ -394,8 +412,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
|||
/* Set up registers for signal handler; preserve the threadptr */
|
||||
tp = regs->threadptr;
|
||||
ps = regs->ps;
|
||||
start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
|
||||
(unsigned long) frame);
|
||||
start_thread(regs, handler, (unsigned long)frame);
|
||||
|
||||
/* Set up a stack frame for a call4 if userspace uses windowed ABI */
|
||||
if (ps & PS_WOE_MASK) {
|
||||
|
@ -413,6 +430,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
|||
regs->areg[base + 4] = (unsigned long) &frame->uc;
|
||||
regs->threadptr = tp;
|
||||
regs->ps = ps;
|
||||
if (fdpic)
|
||||
regs->areg[base + 11] = handler_fdpic_GOT;
|
||||
|
||||
pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
|
||||
current->comm, current->pid, sig, frame, regs->pc);
|
||||
|
|
Loading…
Reference in New Issue