Setting up user-mode handler frames

To set up a stack frame for a user-mode handler, handle_signal() invokes setup_rt_frame() with the address of the instance of ksignal, which contains the k_sigaction associated with the signal and the pointer to struct pt_regs in the kernel stack of the current process.
Following is x86 implementation of setup_rt_frame():

setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
{
int usig = ksig->sig;
sigset_t *set = sigmask_to_save();
compat_sigset_t *cset = (compat_sigset_t *) set;

/* Set up the stack frame */
if (is_ia32_frame(ksig)) {
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
return ia32_setup_rt_frame(usig, ksig, cset, regs); // for 32bit systems with SA_SIGINFO
else
return ia32_setup_frame(usig, ksig, cset, regs); // for 32bit systems without SA_SIGINFO
} else if (is_x32_frame(ksig)) {
return x32_setup_rt_frame(ksig, cset, regs);// for systems with x32 ABI
} else {
return __setup_rt_frame(ksig->sig, ksig, set, regs);// Other variants of x86
}
}

It checks for the specific variant of x86 and invokes the appropriate frame setup routine. For further discussion, we shall focus on __setup_rt_frame(), which applies for x86-64. This function populates an instance of a structure called struct rt_sigframe with information needed to handle the signal, sets up a return path (through the _kernel_rt_sigreturn() function), and pushes it into the user-mode stack:

/*arch/x86/include/asm/sigframe.h */
#ifdef CONFIG_X86_64

struct rt_sigframe {
char __user *pretcode;
struct ucontext uc;
struct siginfo info;
/* fp state follows here */
};

-----------------------

/*arch/x86/kernel/signal.c */
static int __setup_rt_frame(int sig, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
void __user *restorer;
int err = 0;
void __user *fpstate = NULL;

/* setup frame with Floating Point state */
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate);

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT;

put_user_try {
put_user_ex(sig, &frame->sig);
put_user_ex(&frame->info, &frame->pinfo);
put_user_ex(&frame->uc, &frame->puc);

/* Create the ucontext. */
if (boot_cpu_has(X86_FEATURE_XSAVE))
put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
else
put_user_ex(0, &frame->uc.uc_flags);
put_user_ex(0, &frame->uc.uc_link);
save_altstack_ex(&frame->uc.uc_stack, regs->sp);

/* Set up to return from userspace. */
restorer = current->mm->context.vdso +
vdso_image_32.sym___kernel_rt_sigreturn;
if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer;
put_user_ex(restorer, &frame->pretcode);

/*
* This is movl $__NR_rt_sigreturn, %ax ; int $0x80
*
* WE DO NOT USE IT ANY MORE! It's only left here for historical
* reasons and because gdb uses it as a signature to notice
* signal handler stack frames.
*/
put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
} put_user_catch(err);

err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));

if (err)
return -EFAULT;

/* Set up registers for signal handler */
regs->sp = (unsigned long)frame;
regs->ip = (unsigned long)ksig->ka.sa.sa_handler;
regs->ax = (unsigned long)sig;
regs->dx = (unsigned long)&frame->info;
regs->cx = (unsigned long)&frame->uc;

regs->ds = __USER_DS;
regs->es = __USER_DS;
regs->ss = __USER_DS;
regs->cs = __USER_CS;

return 0;
}

The *pretcode field of the rt_sigframe structure is assigned the return address of the signal-handler function, which is the _kernel_rt_sigreturn() routine. struct ucontext uc is initialized with sigcontext, which contains the user-mode context copied from pt_regs of the kernel stack, bit array of regular blocked signals, and floating point state. After setting up and pushing the frame instance to the user-mode stack, __setup_rt_frame() alters pt_regs of the process in the kernel stack to hand over control to the signal handler when the current process resumes execution. The instruction pointer (ip) is set to the base address of the signal handler and the stack pointer (sp) is set to the top address of the frame pushed earlier; these changes cause the signal handler to execute.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.22.169