Skip to content

Commit 9c2cc74

Browse files
committed
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: [email protected] Fixes: e3ddb8b ("xtensa: add FDPIC and static PIE support for noMMU") Signed-off-by: Max Filippov <[email protected]>
1 parent 457391b commit 9c2cc74

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

arch/xtensa/kernel/signal.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,19 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
343343
struct rt_sigframe *frame;
344344
int err = 0, sig = ksig->sig;
345345
unsigned long sp, ra, tp, ps;
346+
unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
347+
unsigned long handler_fdpic_GOT = 0;
346348
unsigned int base;
349+
bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
350+
(current->personality & FDPIC_FUNCPTRS);
351+
352+
if (fdpic) {
353+
unsigned long __user *fdpic_func_desc =
354+
(unsigned long __user *)handler;
355+
if (__get_user(handler, &fdpic_func_desc[0]) ||
356+
__get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
357+
return -EFAULT;
358+
}
347359

348360
sp = regs->areg[1];
349361

@@ -373,29 +385,34 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
373385
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
374386

375387
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
376-
ra = (unsigned long)ksig->ka.sa.sa_restorer;
388+
if (fdpic) {
389+
unsigned long __user *fdpic_func_desc =
390+
(unsigned long __user *)ksig->ka.sa.sa_restorer;
391+
392+
err |= __get_user(ra, fdpic_func_desc);
393+
} else {
394+
ra = (unsigned long)ksig->ka.sa.sa_restorer;
395+
}
377396
} else {
378397

379398
/* Create sys_rt_sigreturn syscall in stack frame */
380399

381400
err |= gen_return_code(frame->retcode);
382-
383-
if (err) {
384-
return -EFAULT;
385-
}
386401
ra = (unsigned long) frame->retcode;
387402
}
388403

389-
/*
404+
if (err)
405+
return -EFAULT;
406+
407+
/*
390408
* Create signal handler execution context.
391409
* Return context not modified until this point.
392410
*/
393411

394412
/* Set up registers for signal handler; preserve the threadptr */
395413
tp = regs->threadptr;
396414
ps = regs->ps;
397-
start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
398-
(unsigned long) frame);
415+
start_thread(regs, handler, (unsigned long)frame);
399416

400417
/* Set up a stack frame for a call4 if userspace uses windowed ABI */
401418
if (ps & PS_WOE_MASK) {
@@ -413,6 +430,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
413430
regs->areg[base + 4] = (unsigned long) &frame->uc;
414431
regs->threadptr = tp;
415432
regs->ps = ps;
433+
if (fdpic)
434+
regs->areg[base + 11] = handler_fdpic_GOT;
416435

417436
pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
418437
current->comm, current->pid, sig, frame, regs->pc);

0 commit comments

Comments
 (0)