mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
xtensa: fix signal delivery to FDPIC process
commit9c2cc74fb3upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
0845660508
commit
522bbbfcb6
@@ -343,7 +343,19 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
|||||||
struct rt_sigframe *frame;
|
struct rt_sigframe *frame;
|
||||||
int err = 0, sig = ksig->sig;
|
int err = 0, sig = ksig->sig;
|
||||||
unsigned long sp, ra, tp, ps;
|
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;
|
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];
|
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));
|
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||||
|
|
||||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
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 {
|
} else {
|
||||||
|
|
||||||
/* Create sys_rt_sigreturn syscall in stack frame */
|
/* Create sys_rt_sigreturn syscall in stack frame */
|
||||||
|
|
||||||
err |= gen_return_code(frame->retcode);
|
err |= gen_return_code(frame->retcode);
|
||||||
|
|
||||||
if (err) {
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
ra = (unsigned long) frame->retcode;
|
ra = (unsigned long) frame->retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (err)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
/*
|
||||||
* Create signal handler execution context.
|
* Create signal handler execution context.
|
||||||
* Return context not modified until this point.
|
* 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 */
|
/* Set up registers for signal handler; preserve the threadptr */
|
||||||
tp = regs->threadptr;
|
tp = regs->threadptr;
|
||||||
ps = regs->ps;
|
ps = regs->ps;
|
||||||
start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
|
start_thread(regs, handler, (unsigned long)frame);
|
||||||
(unsigned long) frame);
|
|
||||||
|
|
||||||
/* Set up a stack frame for a call4 if userspace uses windowed ABI */
|
/* Set up a stack frame for a call4 if userspace uses windowed ABI */
|
||||||
if (ps & PS_WOE_MASK) {
|
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->areg[base + 4] = (unsigned long) &frame->uc;
|
||||||
regs->threadptr = tp;
|
regs->threadptr = tp;
|
||||||
regs->ps = ps;
|
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",
|
pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
|
||||||
current->comm, current->pid, sig, frame, regs->pc);
|
current->comm, current->pid, sig, frame, regs->pc);
|
||||||
|
|||||||
Reference in New Issue
Block a user