/* Store registers needed to create the signal frame */ staticvoid store_sigregs(void)
{
save_access_regs(current->thread.acrs);
save_user_fpu_regs();
}
/* Load registers after signal return */ staticvoid load_sigregs(void)
{
restore_access_regs(current->thread.acrs);
}
/* Copy a 'clean' PSW mask to the user to avoid leaking
information about whether PER is currently on. */
user_sregs.regs.psw.mask = PSW_USER_BITS |
(regs->psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
user_sregs.regs.psw.addr = regs->psw.addr;
memcpy(&user_sregs.regs.gprs, ®s->gprs, sizeof(sregs->regs.gprs));
memcpy(&user_sregs.regs.acrs, current->thread.acrs, sizeof(user_sregs.regs.acrs));
fpregs_store(&user_sregs.fpregs, ¤t->thread.ufpu); if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs))) return -EFAULT; return0;
}
clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */ return0;
}
/* Returns non-zero on fault. */ staticint save_sigregs_ext(struct pt_regs *regs,
_sigregs_ext __user *sregs_ext)
{
__u64 vxrs[__NUM_VXRS_LOW]; int i;
/* Save vector registers to signal stack */ if (cpu_has_vx()) { for (i = 0; i < __NUM_VXRS_LOW; i++)
vxrs[i] = current->thread.ufpu.vxrs[i].low; if (__copy_to_user(&sregs_ext->vxrs_low, vxrs, sizeof(sregs_ext->vxrs_low)) ||
__copy_to_user(&sregs_ext->vxrs_high,
current->thread.ufpu.vxrs + __NUM_VXRS_LOW, sizeof(sregs_ext->vxrs_high))) return -EFAULT;
} return0;
}
/* Default to using normal stack */
sp = regs->gprs[15];
/* Overflow on alternate signal stack gives SIGSEGV. */ if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL)) return (void __user *) -1UL;
/* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
/* Set up backchain. */ if (__put_user(regs->gprs[15], (addr_t __user *) frame)) return -EFAULT;
/* Create struct sigcontext on the signal stack */
memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE);
sc.sregs = (_sigregs __user __force *) &frame->sregs; if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc))) return -EFAULT;
/* Store registers needed to create the signal frame */
store_sigregs();
/* Create _sigregs on the signal stack */ if (save_sigregs(regs, &frame->sregs)) return -EFAULT;
/* Place signal number on stack to allow backtrace from handler. */ if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) return -EFAULT;
/* Create _sigregs_ext on the signal stack */ if (save_sigregs_ext(regs, &frame->sregs_ext)) return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER)
restorer = (unsignedlong) ka->sa.sa_restorer; else
restorer = VDSO64_SYMBOL(current, sigreturn);
/* Set up registers for signal handler */
regs->gprs[14] = restorer;
regs->gprs[15] = (unsignedlong) frame; /* Force default amode and default user address space control. */
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsignedlong) ka->sa.sa_handler;
/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */ if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
sig == SIGTRAP || sig == SIGFPE) { /* set extra registers only for synchronous signals */
regs->gprs[4] = regs->int_code & 127;
regs->gprs[5] = regs->int_parm_long;
regs->gprs[6] = current->thread.last_break;
} return0;
}
/* Set up backchain. */ if (__put_user(regs->gprs[15], (addr_t __user *) frame)) return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = (unsignedlong) ksig->ka.sa.sa_restorer; else
restorer = VDSO64_SYMBOL(current, rt_sigreturn);
/* Create siginfo on the signal stack */ if (copy_siginfo_to_user(&frame->info, &ksig->info)) return -EFAULT;
/* Store registers needed to create the signal frame */
store_sigregs();
/* Create ucontext on the signal stack. */ if (__put_user(uc_flags, &frame->uc.uc_flags) ||
__put_user(NULL, &frame->uc.uc_link) ||
__save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
save_sigregs(regs, &frame->uc.uc_mcontext) ||
__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
save_sigregs_ext(regs, &frame->uc.uc_mcontext_ext)) return -EFAULT;
/* Set up registers for signal handler */
regs->gprs[14] = restorer;
regs->gprs[15] = (unsignedlong) frame; /* Force default amode and default user address space control. */
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsignedlong) ksig->ka.sa.sa_handler;
/* Set up the stack frame */ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(ksig, oldset, regs); else
ret = setup_frame(ksig->sig, &ksig->ka, oldset, regs);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.