bool emulate_vsyscall(unsignedlong error_code, struct pt_regs *regs, unsignedlong address)
{ unsignedlong caller; int vsyscall_nr, syscall_nr, tmp; long ret; unsignedlong orig_dx;
/* Write faults or kernel-privilege faults never get fixed up. */ if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER) returnfalse;
/* *Assumethatfaultsatregs->iparebecauseofan *instructionfetch.Returnearlyandavoid *emulationforfaultsduringdataaccesses:
*/ if (address != regs->ip) { /* Failed vsyscall read */ if (vsyscall_mode == EMULATE) returnfalse;
/* *Usercodetriedandfailedtoreadthevsyscallpage.
*/
warn_bad_vsyscall(KERN_INFO, regs, "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround"); returnfalse;
}
/* *X86_PF_INSTRisonlysetwhenNXissupported.When *available,useittodouble-checkthattheemulationcode *isonlybeingusedforinstructionfetches:
*/ if (cpu_feature_enabled(X86_FEATURE_NX))
WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
if (vsyscall_mode == NONE) {
warn_bad_vsyscall(KERN_INFO, regs, "vsyscall attempted with vsyscall=none"); returnfalse;
}
vsyscall_nr = addr_to_vsyscall_nr(address);
trace_emulate_vsyscall(vsyscall_nr);
if (vsyscall_nr < 0) {
warn_bad_vsyscall(KERN_WARNING, regs, "misaligned vsyscall (exploit attempt or buggy program) -- look up the vsyscall kernel parameter if you need a workaround"); goto sigsegv;
}
if (get_user(caller, (unsignedlong __user *)regs->sp) != 0) {
warn_bad_vsyscall(KERN_WARNING, regs, "vsyscall with bad stack (exploit attempt?)"); goto sigsegv;
}
/* *Witharealvsyscall,pagefaultscauseSIGSEGV.
*/
ret = -EFAULT; switch (vsyscall_nr) { case0: /* this decodes regs->di and regs->si on its own */
ret = __x64_sys_gettimeofday(regs); break;
case1: /* this decodes regs->di on its own */
ret = __x64_sys_time(regs); break;
case2: /* while we could clobber regs->dx, we didn't in the past... */
orig_dx = regs->dx;
regs->dx = 0; /* this decodes regs->di, regs->si and regs->dx on its own */
ret = __x64_sys_getcpu(regs);
regs->dx = orig_dx; break;
}
check_fault: if (ret == -EFAULT) { /* Bad news -- userspace fed a bad pointer to a vsyscall. */
warn_bad_vsyscall(KERN_INFO, regs, "vsyscall fault (exploit attempt?)"); goto sigsegv;
}
regs->ax = ret;
do_ret: /* Emulate a ret instruction. */
regs->ip = caller;
regs->sp += 8; returntrue;
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.