我读到我们的系统中有一些特权指令可以在内核模式下执行。但我不明白是谁把这些指令变成了特权指令,是硬件制造商借助模式位把一些有害的指令硬连接成特权指令,还是操作系统的设计者把指令变成了特权指令,使它们只能在特权模式下工作。
内核与用户模式,以及哪些指令不允许在用户模式下执行,是ISA的一部分。 这是硬件的一部分。
CPU架构师通常很清楚操作系统需要做什么,想要阻止用户空间做什么,所以这些选择至少让权限级别成为可能,即让用户空间无法简单地接管机器。
但这还不是全部:在一些ISA上,比如x86,后来的ISA扩展增加了控制寄存器标志位,让操作系统选择其他一些指令是否有特权。 在x86上,这是为可能泄露信息的指令而做的。内核ASLR,或使定时侧通道更容易。
例如: rdpmc
(读取性能监控计数器)只有在内核特别启用的情况下才可以从用户空间使用,但CR4中的TSD(TimeStamp Disable)标志可以限制它在priv level 0(内核模式)下使用。 rdtsc
(Read TimeStamp Counter)默认可以从用户空间读取,但是CR4中的TSD(TimeStamp Disable)标志可以将其限制在priv level 0(内核模式)下使用。 停止用户空间使用高分辨率定时是防御定时侧通道攻击的一种蛮力方式。
另一个x86扩展可以防御内核地址的泄露,使内核ASLR更加秘密;CR4.UMIP(User Mode Instruction Prevention,用户模式指令预防)可以禁用类似于 sgdt
,读取GDT的虚拟地址。 这些指令对于用户空间来说,基本上是无用的,首先不像 rdtsc
很容易被赋予特权。
Linux内核的选项可以使用这个扩展功能 描写:
用户模式指令预防(UMIP)是较新的英特尔处理器的一个安全功能。如果启用,如果在用户模式下执行SGDT、SLDT、SIDT、SMSW或STR指令,则会发出一般保护故障。这些指令会不必要地暴露硬件状态的信息。
绝大多数应用程序不使用这些指令。对于极少数使用这些指令的应用程序,在特定情况下,在保护模式和虚拟8086模式下提供软件仿真。仿真的结果是假的。
为IDTGDTLDT设置新的地址(如? lgdt/lidt
)当然是一个特权指令,那些让你接管机器。 但是,在内核ASLR成为一个东西之前,没有任何理由阻止用户空间读取地址。 它可能在一个页面中,它的页表条目只被设置为内核,阻止用户空间对该地址做任何事情。 (......直到Meltdown让用户空间可以使用一个推测性的侧通道来读取缓存中热的只属于内核的页面的数据。)