@@ -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