// SPDX-License-Identifier: GPL-2.0-only /* * single_step_syscall.c - single-steps various x86 syscalls * Copyright (c) 2014-2015 Andrew Lutomirski * * This is a very simple series of tests that makes system calls with * the TF flag set. This exercises some nasty kernel code in the * SYSENTER case: SYSENTER does not clear TF, so SYSENTER with TF set * immediately issues #DB from CPL 0. This requires special handling in * the kernel.
*/
/* * This test is particularly interesting if fast syscalls use * SYSENTER: it triggers a nasty design flaw in SYSENTER. * Specifically, SYSENTER does not clear TF, so either SYSENTER * or the next instruction traps at CPL0. (Of course, Intel * mostly forgot to document exactly what happens here.) So we * get a CPL0 fault with usergs (on 64-bit kernels) and possibly * no stack. The only sane way the kernel can possibly handle * it is to clear TF on return from the #DB handler, but this * happens way too early to set TF in the saved pt_regs, so the * kernel has to do something clever to avoid losing track of * the TF bit. * * Needless to say, we've had bugs in this area.
*/
syscall(SYS_getpid); /* Force symbol binding without TF set. */
printf("[RUN]\tSet TF and check a fast syscall\n");
set_eflags(get_eflags() | X86_EFLAGS_TF);
syscall(SYS_getpid);
check_result();
/* Now make sure that another fast syscall doesn't set TF again. */
fast_syscall_no_tf();
/* * And do a forced SYSENTER to make sure that this works even if * fast syscalls don't use SYSENTER. * * Invoking SYSENTER directly breaks all the rules. Just handle * the SIGSEGV.
*/ if (sigsetjmp(jmpbuf, 1) == 0) { unsignedlong nr = SYS_getpid;
printf("[RUN]\tSet TF and check SYSENTER\n");
stack_t stack = {
.ss_sp = malloc(sizeof(char) * SIGSTKSZ),
.ss_size = SIGSTKSZ,
}; if (sigaltstack(&stack, NULL) != 0)
err(1, "sigaltstack");
sethandler(SIGSEGV, print_and_longjmp,
SA_RESETHAND | SA_ONSTACK);
sethandler(SIGILL, print_and_longjmp, SA_RESETHAND);
set_eflags(get_eflags() | X86_EFLAGS_TF);
free(stack.ss_sp); /* Clear EBP first to make sure we segfault cleanly. */ asmvolatile ("xorl %%ebp, %%ebp; SYSENTER" : "+a" (nr) :: "flags", "rcx" #ifdef __x86_64__
, "r11" #endif
);
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.