lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250901162527.18247-2-samuele@cerea.dev>
Date: Mon,  1 Sep 2025 18:25:28 +0200
From: Samuele Cerea <samuele@...ea.dev>
To: bp@...en8.de
Cc: x86@...nel.org,
	linux-kernel@...r.kernel.org,
	tglx@...utronix.de,
	mingo@...hat.com,
	dave.hansen@...ux.intel.com,
	Samuele Cerea <samuele@...ea.dev>
Subject: [PATCH v2] x86/traps: Handle trap flag when instruction is emulated

Simulate the trap flag (TF) behavior when the kernel emulates UIMP
instructions and iopl instructions.

When an instruction is emulated successfully and the TF is set, send a
SIGTRAP signal to the process, as it would happen for a normally
executed instruction.

Fix a problem with debuggers when signle-stepping instructions where
emulated instruction would get skipped.

Here is an example of the problem:
    NOP
    SLDT %rax
    SLDT %rax
    NOP
The two SLDT instructions will be skipped an the debugger will step
directly to the second NOP instruction.

Signed-off-by: Samuele Cerea <samuele@...ea.dev>
---
I fixed the issues you pointed out, hopefully now everything is correct

 arch/x86/include/asm/traps.h |  2 ++
 arch/x86/kernel/traps.c      | 14 ++++++++++++++
 arch/x86/kernel/umip.c       |  1 +
 3 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 869b88061801..7742a6d05158 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -39,6 +39,8 @@ void math_emulate(struct math_emu_info *);
 
 bool fault_in_kernel_space(unsigned long address);
 
+void emulate_trap_flag(struct pt_regs *regs);
+
 #ifdef CONFIG_VMAP_STACK
 void __noreturn handle_stack_overflow(struct pt_regs *regs,
 				      unsigned long fault_address,
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 36354b470590..bea28473866b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -678,6 +678,19 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
 
 #define GPFSTR "general protection fault"
 
+void emulate_trap_flag(struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+
+	/* If the instruction was emulated successfully, emulate trap flag */
+	if (regs->flags & X86_EFLAGS_TF) {
+		tsk->thread.cr2 = regs->ip;
+		tsk->thread.trap_nr = X86_TRAP_DB;
+		tsk->thread.error_code = 0;
+		force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)regs->ip);
+	}
+}
+
 static bool fixup_iopl_exception(struct pt_regs *regs)
 {
 	struct thread_struct *t = &current->thread;
@@ -705,6 +718,7 @@ static bool fixup_iopl_exception(struct pt_regs *regs)
 	}
 
 	regs->ip += 1;
+	emulate_trap_flag(regs);
 	return true;
 }
 
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 5a4b21389b1d..8a5f33562bb4 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -407,5 +407,6 @@ bool fixup_umip_exception(struct pt_regs *regs)
 
 	/* increase IP to let the program keep going */
 	regs->ip += insn.length;
+	emulate_trap_flag(regs);
 	return true;
 }
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ