SuspendThread WOW64在内核代码中挂起 [英] SuspendThread WOW64 suspending in kernel code

查看:842
本文介绍了SuspendThread WOW64在内核代码中挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UPDATE :Microsoft尚未在Windows 8.1中修复它。



编辑 :结果是错误 - 当线程在长模式ring-3(用户模式)中挂起时,GetThreadContext()可能返回过期的内容。我建议微软使用ring-2来执行翻译。 SuspendThread然后只会挂起环3中的线程(因为它现在 - 不需要更改),并且环-2中的崩溃/故障/漏洞不会影响内核 - 它只会影响环-2和环 - 3。



这样的更改将需要更改一些WinAPI函数,如Wow64Get / SetThreadContext等。这将打破依赖于无文档功能的应用程序,但这是预期的。授权,转换将会更慢,因为它需要几个CPU周期从环3转换到环-2(取决于CPU系列),但我认为操作系统的作用首先是确保正确的操作。



我希望Microsoft能解决这个问题,否则调试器/ Mono apps / Boehm GC / apps依赖于WOW64下的GetThreadContext()不起作用(对于初学者,我看到调试器显示陈旧的堆栈跟踪)。



EDIT2 :坏消息。根据我与MSFT的Alexey的对话(这里 )它看起来好像它可能不会固定在所有的恐惧,修复会打破依赖于无证书的功能的应用程序。






原始问题




  • 有些人似乎对以下内容感到困惑。我最初认为是由于SuspendThread挂起一个线程在内核模式代码。它不是。下面只是我最初的怀疑,结果是与实际的根本原因无关 - 这是由 GetThreadContext()返回的过时的内容。



从MSDN:



挂起线程会使线程停止执行用户模式(应用程序)代码。



然而,我发现我的32位应用程序在Windows 7运行下WOW64,线程B上的线程A调用SuspendThread可以暂停它,当它运行64位代码(我期望是不是用户模式代码)。 EIP显示暂停的线程停止在

  wow64cpu!X86SwitchTo64BitMode:
00000000`759c31b0 ea27369c753300 jmp 0033:759C3627 $ b $它的ESP已经改变(我知道这是因为,虽然ESP指向与该线程的堆栈相同的页面)b



,它有一个比当前堆栈指针高得多的地址)。如果我把断点放在上面返回的指令,然后让线程恢复,我发现ESP改回回到X86SwitchTo64BitMode调用之前的值(这是正确的堆栈指针)。我还发现,当单步进入相同的功能,我不能在单步的任何点获得更高的地址ESP值。事实上,当单步执行时,ESP值在X86SwitchTo64BitMode调用之前和之后永远不会改变。



此外,我确保SuspendThread通过检查(DWORD)-1成功。



所有这些都让我相信线程在内核模式代码中被暂停。



导致操作系统在运行非用户模式代码时挂起线程?如何防止这种情况?这基本上阻止我获得线程B的实际当前堆栈指针。请注意,当应用程序运行在WOW64之外(在本机x86操作系统),没有这样的问题存在。



=http://social.msdn.microsoft.com/Forums/en-US/windowscompatibility/thread/1558e9ca-8180-4633-a349-534e8d51cf3a/?prof=required =nofollow>更多信息< a>。



感谢尝试回答这个问题的每个人。我正在与MS一起解决这个问题。


UPDATE: Microsoft have yet to fix it in Windows 8.1.

EDIT: This turned out to be a bug in WOW64 - GetThreadContext() may return stale contents when the thread is suspended in long mode ring-3 (user mode). I've suggested to Microsoft to use ring-2 to perform the translation. SuspendThread would then only suspend thread in ring-3 (as it does now - no changes necessary), and a crash/fault/exploit in ring-2 won't affect the kernel - it'd only affect ring-2 and ring-3.

Such changes would necessitate the change of a few WinAPI functions such as Wow64Get/SetThreadContext etc. This would break apps relying on undocumented features but that's to be expected. Granted, translation would be slower as it takes a few CPU cycles to transition from ring-3 to ring-2 (depending on the CPU family) but I'd think that the role of the OS is first and foremost to ensure correct operation. Translation already adds overhead to apps running under WOW64, so that's to be expected too.

I do hope that Microsoft would fix this issue - otherwise debuggers / Mono apps / Boehm GC / apps that rely on GetThreadContext() under WOW64 would not work (for starters, I've seen debuggers show stale stack trace).

EDIT2: Bad news. From my conversation with Alexey from MSFT (here) it looks as though it may not get fixed at all in fear that the fix would break apps that rely on undocumented features.


Original question

  • Some people seem to be confused about the following. I initially thought it was due to SuspendThread suspending a thread while in kernel-mode code. It wasn't. The following was merely my initial suspicion which turned out to have nothing to do with the actual root cause -- which was the stale contents returned by GetThreadContext().

From MSDN:

Suspending a thread causes the thread to stop executing user-mode (application) code.

What I've found however is that my 32-bit app in Windows 7 running under WOW64, Thread A calling SuspendThread on Thread B can pause it while it's running 64-bit code (which I would expect is not user-mode code). EIP shows the suspended thread stopped at

wow64cpu!X86SwitchTo64BitMode:
00000000`759c31b0 ea27369c753300  jmp     0033:759C3627

with its ESP having changed (I know this because, while the ESP is pointing to the same page as that thread's stack, it's got a much higher address than the current stack pointer). If I put a breakpoint at the instruction which the above returns to, and then get the thread to resume, I found that the ESP changes back to the value before the X86SwitchTo64BitMode call (which is the correct stack pointer). I also found that when single stepping into the same function, I can never get that higher address ESP value at any point of the single step. In fact, when single stepping, ESP value never changes before and after the X86SwitchTo64BitMode call.

Also, I did make sure SuspendThread succeed by checking against (DWORD)-1.

All of these leads me to believe that the thread is suspended in kernel-mode code.

What could be causing the OS to suspend a thread while it's running non-user-mode code? How do I prevent that? This is basically preventing me from getting the actual current stack pointer of Thread B. Note that when the app runs outside of WOW64 (on native x86 OS), no such problem exists.

解决方案

I've confirmed that this is an OS issue returning stale contents when GetThreadContext is called under WOW64.

More info here.

Thanks to everyone who attempted to answer this question. I'm working with MS to resolve this.

这篇关于SuspendThread WOW64在内核代码中挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆