/* * The first GDT descriptor is reserved as 'NULL descriptor'. As bits 0 * and 1 of a segment selector, i.e., the RPL bits, are NOT used to index * GDT, selector values 0~3 all point to the NULL descriptor, thus values * 0, 1, 2 and 3 are all valid NULL selector values. * * However IRET zeros ES, FS, GS, and DS segment registers if any of them * is found to have any nonzero NULL selector value, which can be used by * userspace in pre-FRED systems to spot any interrupt/exception by loading * a nonzero NULL selector and waiting for it to become zero. Before FRED * there was nothing software could do to prevent such an information leak. * * ERETU, the only legit instruction to return to userspace from kernel * under FRED, by design does NOT zero any segment register to avoid this * problem behavior. * * As such, leave NULL selector values 0~3 unchanged.
*/ staticinline u16 fixup_rpl(u16 sel)
{ return sel <= 3 ? sel : sel | 3;
}
/* * Reload fs and gs if they have changed in the signal * handler. This does not handle long fs/gs base changes in * the handler, but does not clobber them at least in the * normal case.
*/
savesegment(gs, cur); if (fixup_rpl(sc->gs) != cur)
load_gs_index(fixup_rpl(sc->gs));
savesegment(fs, cur); if (fixup_rpl(sc->fs) != cur)
loadsegment(fs, fixup_rpl(sc->fs));
savesegment(ds, cur); if (fixup_rpl(sc->ds) != cur)
loadsegment(ds, fixup_rpl(sc->ds));
savesegment(es, cur); if (fixup_rpl(sc->es) != cur)
loadsegment(es, fixup_rpl(sc->es));
}
/* * Do a signal return; undo the signal stack.
*/ staticbool ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_32 __user *usc)
{ struct sigcontext_32 sc;
/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
if (unlikely(copy_from_user(&sc, usc, sizeof(sc)))) returnfalse;
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
restorer = ksig->ka.sa.sa_restorer;
} else { /* Return stub is in 32bit vsyscall page */ if (current->mm->context.vdso)
restorer = current->mm->context.vdso +
vdso_image_32.sym___kernel_sigreturn; else
restorer = &frame->retcode;
}
if (!user_access_begin(frame, sizeof(*frame))) return -EFAULT;
unsafe_put_user(ksig->sig, &frame->sig, Efault);
unsafe_put_sigcontext32(&frame->sc, fp, regs, set, Efault);
unsafe_put_user(set->sig[1], &frame->extramask[0], Efault);
unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault); /* * These are actually not used anymore, but left because some * gdb versions depend on them as a marker.
*/
unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault);
user_access_end();
/* Set up registers for signal handler */
regs->sp = (unsignedlong) frame;
regs->ip = (unsignedlong) ksig->ka.sa.sa_handler;
/* Make -mregparm=3 work */
regs->ax = ksig->sig;
regs->dx = 0;
regs->cx = 0;
/* * Not actually used anymore, but left because some gdb * versions need it.
*/
unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault);
unsafe_put_sigcontext32(&frame->uc.uc_mcontext, fp, regs, set, Efault);
unsafe_put_user(*(__u64 *)set, (__u64 __user *)&frame->uc.uc_sigmask, Efault);
user_access_end();
if (__copy_siginfo_to_user32(&frame->info, &ksig->info)) return -EFAULT;
/* Set up registers for signal handler */
regs->sp = (unsignedlong) frame;
regs->ip = (unsignedlong) ksig->ka.sa.sa_handler;
/* Make -mregparm=3 work */
regs->ax = ksig->sig;
regs->dx = (unsignedlong) &frame->info;
regs->cx = (unsignedlong) &frame->uc;
/* * The siginfo_t structure and handing code is very easy * to break in several ways. It must always be updated when new * updates are made to the main siginfo_t, and * copy_siginfo_to_user32() must be updated when the * (arch-independent) copy_siginfo_to_user() is updated. * * It is also easy to put a new member in the siginfo_t * which has implicit alignment which can move internal structure * alignment around breaking the ABI. This can happen if you, * for instance, put a plain 64-bit value in there.
*/
/* * 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(siginfo32_t) == 128);
/* This is a part of the ABI and can never change in alignment */
static_assert(__alignof__(siginfo32_t) == 4);
/* * 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(siginfo32_t, _sifields) == 3 * sizeof(int));
/* * 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.