【问题标题】:How does a software-based context-switch with TSS work? [closed]使用 TSS 的基于软件的上下文切换如何工作? [关闭]
【发布时间】:2016-06-20 02:16:18
【问题描述】:

我想知道 TSS(任务状态段)的简单解释以及它如何用于进行基于软件的上下文切换。

【问题讨论】:

  • 为什么不清楚我在问什么?我的意思是答案非常准确。这就是我所要求的。

标签: x86 operating-system


【解决方案1】:

首先,TSS 是一个历史性的缺陷。曾几何时(又名:1980 年代初期),英特尔的人们坚称硬件上下文切换而不是软件上下文切换是一个好主意。他们大错特错。硬件上下文切换有几个明显的缺点,并且由于它从未被适当地实现,因此性能很差。由于所有这些,甚至没有健全的操作系统实现它,而且它的可移植性甚至不如分段。详情请见the obscure corner of OSDevers

现在,关于任务状态段。如果任何操作系统实现了硬件上下文切换,它的目的是代表一个“任务”。可以将线程和进程都表示为“任务”,但通常情况下,在我们使用硬件上下文切换的少数代码中,它表示一个简单的进程。 TSS 将保存诸如任务的通用寄存器内容、控制寄存器(CR0、CR2、CR3 和 CR4;没有 CR1)、CPU 标志和指令指针等内容......

然而,在软件执行所有上下文切换的现实世界中,我们留下了一个(几乎)无用的 104 字节长的结构。然而,正如我们所说的英特尔,它从未被弃用/删除,操作系统必须处理它。

问题其实很简单。假设您在典型的用户模式进程中运行典型的foo() 函数。突然,您,用户,按下 Windows/Meta/Super/however-you-call-it 键以启动您的邮件客户端。结果,中断请求 (IRQ) 从键盘发送到中断控制器(8259A PIC 或 IOAPIC)。然后,中断控制器安排事情以触发 CPU 中断。 CPU 进入特权级 0,寄存器连同中断号一起被压入,并调用内核模式代码来处理这种情况。等待!推东西?在哪里?当然是在堆栈上!但是,为了定义“堆栈”,堆栈指针是从哪里获取的?

如果你碰巧使用了用户模式堆栈指针, 会发生不好的事情,并且会出现巨大的安全漏洞。如果堆栈指针指向无效地址会发生什么?它可能发生。毕竟,严格来说,堆栈指针只是另一个通用寄存器,而众所周知,汇编程序员为了硬核而以这种方式使用它。

尝试将内容推送到那里会产生 CPU 异常,很好!而且,由于双重故障​​(尝试处理中断时发生的异常)将再次尝试推翻无效指针,操作系统最糟糕的噩梦变成了现实:三重故障。你有没有见过你的电脑在没有任何事先建议的情况下突然重启?那是三重故障(或电源故障)。操作系统没有改变来处理三重故障,它只是重新启动所有东西。

很好,系统已重新启动。但是,更糟糕的事情可能发生了。如果攻击者故意写入一个关键内核变量的地址(!),并将他想要写入的值按正确的顺序放置在那里,那么随着获得超级用户权限变得比以往任何时候都更容易,让最大的权限提升漏洞占主导地位! GDB、内核配置(在/proc/config.gz 中找到,以及编译内核所用的 GCC 版本足以做到这一点。

现在,回到 TSS,碰巧前面提到的结构包含堆栈指针和堆栈段寄存器的值,这些值在特权级别 3(用户模式)下在中断时加载。内核将其设置为指向内核域中的安全堆栈。因此,系统中每个线程都有一个“内核堆栈”,系统中每个逻辑 CPU 都有一个 TSS。在线程切换时,内核只需更改正确 TSS 中的这两个变量。不,每个逻辑 CPU 不能有一个内核堆栈,因为内核本身可能被抢占(大部分时间)。

我希望这对你有所启发!

【讨论】:

    猜你喜欢
    • 2013-08-03
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    相关资源
    最近更新 更多