【问题标题】:In modern Linux x86-64 is it safe for userspace to overwrite the GS register?在现代 Linux x86-64 中,用户空间覆盖 GS 寄存器是否安全?
【发布时间】:2020-04-24 11:15:33
【问题描述】:

在 64 位 C 程序中,使用 glibc、pthreads 等(没有什么特别的),在当前内核和 glibc 版本上覆盖 GS 寄存器而不恢复它是否安全?我知道 pthreads/glibc 使用 FS 寄存器作为线程本地存储块指针,所以弄乱它会破坏任何使用 TLS 的东西,但我不确定 GS

如果不是,保存该值,覆盖它,然后恢复该值是安全的,只要覆盖时的用户态代码不执行 X(X 是什么)?

【问题讨论】:

  • 是的,但您可能需要arch_prctl(ARCH_SET_GS, foo);
  • @Jester - 通常,也许是的 - 但在这里我想用它作为一个肮脏的黑客来检测中断(如here 所述重置 fs 和 gs),作为分析其他内容的一部分,因此需要避免系统调用(我假设 arch_prtrl 在幕后使用)。

标签: linux assembly pthreads x86-64 memory-segmentation


【解决方案1】:

我不确定; Jester 说“是的,但你可能会想要arch_prctl(ARCH_SET_GS, foo);

或者在具有 FSGSBASE 的 CPU 上,如果内核(例如 Linux 5.9 或更高版本)启用用户空间使用,则可能来自用户空间的 wrgsbase。 (CR4.FSGSBASE[bit 16] 必须设置,否则 #UD 会出错)。

我知道 x86-64 切换到使用 FS 进行 TLS(32 位使用 GS)是因为 syscall 入口点如何使用 swapgs 来查找内核堆栈。

我认为这只是为了内核 TLS / per-core 的用户和内核之间的一致性,因为 64 位内核下的 32 位进程仍然使用 GS 进行 TLS。除了 32 位进程不能使用syscall(AMD CPU 除外)。仅此一点并不能排除一些只为 64 位进程执行的代码,这些代码可以用 GS 做一些事情,但可能没有问题。

swapgs 只交换 GS 基础,而不交换选择器。我不知道是否有任何内核入口点会用一些默认选择器值重写 GS(然后重新加载保存的 GS 基础)。我猜不会。

【讨论】:

  • 谢谢,我希望它能够根据this 检测中断。
猜你喜欢
  • 1970-01-01
  • 2013-10-30
  • 2019-10-06
  • 2022-01-15
  • 2015-08-08
  • 2013-03-14
  • 2011-09-30
  • 2012-07-22
  • 2014-11-26
相关资源
最近更新 更多