内核模式下的线程本地存储?

val*_*ldo 9 windows winapi kernel thread-local-storage

Windows中的内核模式驱动程序是否存在线程局部存储(TLS)等效(确切地说是Win32)?

我试图实现的目标:

最终,在我的驱动程序的调度程序中,它可能会调用许多其他函数(可能存在深度调用).我想提供一些特定于正在处理的请求的上下文信息.也就是说,我有一些结构,指针应该在所有被调用的函数中都可见,而不是将它作为参数显式传递给每个函数.

使用static/global不是一个完美的选择(多线程,同步对象等).

如果那是用户模式代码 - 在这种情况下显然会使用TLS.但是AFAIK没有像TlsGetValue/ 这样的内核模式功能TlsSetValue.这是有道理的 - 要使这些功能工作,必须首先分配一个进程范围的TLS索引.OTOH驱动程序代码可以在任意线程上调用,不限于特定进程.

但是,我实际上并不需要持久的特定于线程的存储.我只需要一个特定于线程的存储来进行顶级函数调用.

我想我知道如何以一种黑客的方式"实施"TLS.我将始终使用预定义的索引(例如,index = 0),而不是分配TLS索引.在顶级函数中,我将保存存储的TLS值,并用所需的值覆盖它.完成后,将恢复保存的值.

幸运的是我知道如何在Win32中实现TLS.TIB每个线程都有一个结构(线程信息块).在每个线程中,可以使用FS:[18h]选择器访问它.在TIB包含(除其他外)通过TLS使用的阵列.其余的非常简单.

但是,我更愿意使用官方API来实现类似的功能.

  • 是否有官方的内核模式API来实现我的需求?
  • 有理由避免我打算做的事吗?我知道重新进入可能存在问题(即一些代码调用我,我覆盖TLS值,然后最终调用原始代码,这可能依赖于TLS).但在我的具体情况下,这是不可能的?
  • 有没有那么脏的方法来解决这个问题?

提前致谢.

PS One理论上可以使用SEH(也存储每线程信息).也就是说,包装顶级代码__try/__except,然后在需要上下文信息的地方 - 用一些参数引发可持续异常,在__except块中用上下文信息填充参数,然后恢复执行.这是一个100%有效的程序流程,不使用未记录的功能.但对我来说这似乎是一个丑陋的黑客,更不用说性能并发症了.

Har*_*ton 8

而不是使用FS:[18h]你应该使用PsGetCurrentThreadTeb.即便如此,我认为您将依赖可能在未来的OS版本中发生变化的细节(可能包括服务包).

相反,您不能使用KeGetCurrentProcessorNumber作为数组的索引,您可以在其中存储指向上下文信息的指针吗?(当然,如果您在DISPATCH_LEVEL或更高级别运行,那么您将无法意外地切换到其他处理器.)

如果不能保证在DISPATCH_LEVEL上运行,则可以使用表或链表,每个条目(表示当前正在运行代码的线程)标记为PsGetCurrentThread的值.


小智 5

不要用TEB这么做!TIB和TEB是用户模式结构。在驱动程序运行时,用户模式应用程序可以从另一个线程/处理器随意修改这些内容。这将是驱动程序中的特权升级漏洞。

我建议您为与您的请求相关的短暂上下文传递上下文结构。如果需要更永久的东西,可以使用AVL表或哈希表,在线程退出时进行清理。

  • +1用于发现漏洞。但是请注意,OP已经解释了为什么他不能使用上下文结构(他需要来自对象析构函数的上下文,不能向其传递参数),并且他已经在使用表并且想要更高效的东西。 (2认同)