Skip to content

Commit

Permalink
xtensa: fix signal delivery to FDPIC process
Browse files Browse the repository at this point in the history
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: e3ddb8b ("xtensa: add FDPIC and static PIE support for noMMU")
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
  • Loading branch information
Max Filippov committed May 12, 2023
1 parent 457391b commit 9c2cc74
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions arch/xtensa/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down Expand Up @@ -373,29 +385,34 @@ 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.
*/

/* 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) {
Expand All @@ -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);
Expand Down

0 comments on commit 9c2cc74

Please sign in to comment.