From 1f25a69feb148c78c89f5dd4c6bce8012dd74107 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:43:48 +0200 Subject: [PATCH] Fix UB in the ps2d vmmouse implementation The vm call will clobber edi, which is the register in which we saved the ebx value. Also make sure to preserve the entire rbx value, rather than just the lower half in ebx. --- ps2d/src/vm.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ps2d/src/vm.rs b/ps2d/src/vm.rs index 5d691cee86..c6c818e9f3 100644 --- a/ps2d/src/vm.rs +++ b/ps2d/src/vm.rs @@ -35,13 +35,27 @@ pub unsafe fn cmd(cmd: u32, arg: u32) -> (u32, u32, u32, u32) { // ebx can't be used as input or output constraint in rust as LLVM reserves it. // Use xchg to pass it through r9 instead while restoring the original value in - // rbx when leaving the inline asm block. + // rbx when leaving the inline asm block. si and di are clobbered too. + #[cfg(not(target_arch = "x86"))] asm!( - "xchg edi, ebx; in eax, dx; xchg edi, ebx", + "xchg r9, rbx; in eax, dx; xchg r9, rbx", inout("eax") MAGIC => a, - inout("edi") arg => b, + inout("r9") arg => b, inout("ecx") cmd => c, inout("edx") PORT as u32 => d, + out("rsi") _, + out("rdi") _, + ); + + // On x86 we don't have a spare register, so push ebx to the stack instead. + #[cfg(target_arch = "x86")] + asm!( + "push ebx; mov ebx, esi; in eax, dx; mov esi, ebx; pop ebx", + inout("eax") MAGIC => a, + inout("esi") arg => b, + inout("ecx") cmd => c, + inout("edx") PORT as u32 => d, + out("edi") _, ); (a, b, c, d)