/* * If regs->ss will cause an IRET fault, change it. Otherwise leave it * alone. Using this generally makes no sense unless * user_64bit_mode(regs) would return true.
*/ staticvoid force_valid_ss(struct pt_regs *regs)
{
u32 ar; asmvolatile ("lar %[old_ss], %[ar]\n\t" "jz 1f\n\t"/* If invalid: */ "xorl %[ar], %[ar]\n\t"/* set ar = 0 */ "1:"
: [ar] "=r" (ar)
: [old_ss] "rm" ((u16)regs->ss));
/* * For a valid 64-bit user context, we need DPL 3, type * read-write data or read-write exp-down data, and S and P * set. We can't use VERW because VERW doesn't check the * P bit.
*/
ar &= AR_DPL_MASK | AR_S | AR_P | AR_TYPE_MASK; if (ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA) &&
ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))
regs->ss = __USER_DS;
}
/* * Fix up SS if needed for the benefit of old DOSEMU and * CRIU.
*/ if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs)))
force_valid_ss(regs);
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault);
unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
unsafe_put_sigmask(set, frame, Efault);
user_access_end();
if (ksig->ka.sa.sa_flags & SA_SIGINFO) { if (copy_siginfo_to_user(&frame->info, &ksig->info)) return -EFAULT;
}
if (setup_signal_shadow_stack(ksig)) return -EFAULT;
/* Set up registers for signal handler */
regs->di = ksig->sig; /* In case the signal handler was declared without prototypes */
regs->ax = 0;
/* This also works for non SA_SIGINFO handlers because they expect the
next argument after the signal number on the stack. */
regs->si = (unsignedlong)&frame->info;
regs->dx = (unsignedlong)&frame->uc;
regs->ip = (unsignedlong) ksig->ka.sa.sa_handler;
regs->sp = (unsignedlong)frame;
/* * Set up the CS and SS registers to run signal handlers in * 64-bit mode, even if the handler happens to be interrupting * 32-bit or 16-bit code. * * SS is subtle. In 64-bit mode, we don't need any particular * SS descriptor, but we do need SS to be valid. It's possible * that the old SS is entirely bogus -- this can happen if the * signal we're trying to deliver is #GP or #SS caused by a bad * SS value. We also have a compatibility issue here: DOSEMU * relies on the contents of the SS register indicating the * SS value at the time of the signal, even though that code in * DOSEMU predates sigreturn's ability to restore SS. (DOSEMU * avoids relying on sigreturn to restore SS; instead it uses * a trampoline.) So we do our best: if the old SS was valid, * we keep it. Otherwise we replace it.
*/
regs->cs = __USER_CS;
if (unlikely(regs->ss != __USER_DS))
force_valid_ss(regs);
return 0;
Efault:
user_access_end(); return -EFAULT;
}
/* * Do a signal return; undo the signal stack.
*/
SYSCALL_DEFINE0(rt_sigreturn)
{ struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame;
sigset_t set; unsignedlong uc_flags;
prevent_single_step_upon_eretu(regs);
frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); if (!access_ok(frame, sizeof(*frame))) goto badframe; if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask)) goto badframe; if (__get_user(uc_flags, &frame->uc.uc_flags)) goto badframe;
set_current_blocked(&set);
if (restore_altstack(&frame->uc.uc_stack)) goto badframe;
if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags)) goto badframe;
if (in_ia32_syscall())
act->sa.sa_flags |= SA_IA32_ABI; if (in_x32_syscall())
act->sa.sa_flags |= SA_X32_ABI;
} #endif/* CONFIG_COMPAT */
/* * If adding a new si_code, there is probably new data in * the siginfo. Make sure folks bumping the si_code * limits also have to look at this code. Make sure any * new fields are handled in copy_siginfo_to_user32()!
*/
static_assert(NSIGILL == 11);
static_assert(NSIGFPE == 15);
static_assert(NSIGSEGV == 10);
static_assert(NSIGBUS == 5);
static_assert(NSIGTRAP == 6);
static_assert(NSIGCHLD == 6);
static_assert(NSIGSYS == 2);
/* This is part of the ABI and can never change in size: */
static_assert(sizeof(siginfo_t) == 128);
/* This is a part of the ABI and can never change in alignment */
static_assert(__alignof__(siginfo_t) == 8);
/* * The offsets of all the (unioned) si_fields are fixed * in the ABI, of course. Make sure none of them ever * move and are always at the beginning:
*/
static_assert(offsetof(siginfo_t, si_signo) == 0);
static_assert(offsetof(siginfo_t, si_errno) == 4);
static_assert(offsetof(siginfo_t, si_code) == 8);
/* * Ensure that the size of each si_field never changes. * If it does, it is a sign that the * copy_siginfo_to_user32() code below needs to updated * along with the size in the CHECK_SI_SIZE(). * * We repeat this check for both the generic and compat * siginfos. * * Note: it is OK for these to grow as long as the whole * structure stays within the padding size (checked * above).
*/
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.