Linux系统中使用含cli指令的代码安全测试A20线的可行性及替代方案问询
关于A20线测试中cli指令的安全性疑问解答
先给你吃个定心丸:你担心的CPU硬件永久损坏完全不会发生!咱们一步步拆解你的问题,再给你可行的替代方案:
核心疑问解答
1. cli指令绝对不会搞坏CPU
cli只是让CPU暂时关闭可屏蔽中断(也就是清除标志寄存器里的IF位),这是CPU设计时就支持的合法操作,属于软件层面的状态切换,和硬件损坏半毛钱关系都没有。你遇到的段错误是Linux的保护机制在起作用:普通用户态程序根本没权限执行cli这种特权级指令,系统直接给你发个SIGSEGV终止程序,这是为了防止普通程序乱改系统状态,完全是安全的保护措施,不管是物理机还是虚拟机,重启程序甚至系统都不会有任何残留影响。
2. 这份A20代码的逻辑是安全的,但不能在用户态跑
先看代码里的细节:
- 开头
pushf保存了标志寄存器,结尾popf恢复,其中就包含了中断开关的状态,所以如果能完整执行完,是会把中断状态还原的; - 代码也正确保存/恢复了所有用到的寄存器,还把修改的内存内容复原了,逻辑上是严谨的。
但问题在于:这份代码是给实模式(比如BIOS启动阶段)写的,不是给Linux用户态程序用的!在Linux用户态,你不仅碰不了cli这种特权指令,连代码里访问的0x0500、0xffff0510都是物理内存地址——Linux用虚拟内存把用户程序和物理内存隔离开了,你访问的地址都是虚拟地址,根本不是实模式下的物理内存,所以就算绕开cli的问题,后面的内存操作也完全不符合预期。
至于能不能用sudo跑?别试,没用——sudo只是提升了用户权限,但程序还是在用户态跑,依然没资格执行特权指令。只有内核态或者实模式下,才能用cli。
3. 底层替代测试方案
如果你想正经测试A20线状态,有几个靠谱的底层方案:
- 写Linux内核模块:内核态拥有最高特权,可以执行
cli,也能通过ioremap访问物理内存。把这份A20检测逻辑改写成内核模块,加载后用printk或者sysfs输出结果就行; - 用QEMU写引导程序:在QEMU虚拟机里写个简单的引导扇区(实模式下运行),把这份A20检测代码放进去,直接模拟BIOS环境,既能正常执行所有指令,又完全不会影响宿主系统;
- 读内核暴露的状态文件:有些Linux发行版会把A20线状态暴露在
/sys/devices/system/x86/a20或者类似的proc/sys路径下,直接cat这个文件就能拿到结果,不用自己写底层代码。
附:你提供的相关代码与调试信息
待测试的A20线检测代码
.func CheckA20 CheckA20: pushf # Save registers that push ds # we are going to push es # overwrite. push di push si cli # No interrupts, please xor ax, ax # Set es:di = 0000:0500 mov es, ax mov di, 0x0500 mov ax, 0xffff # Set ds:si = ffff:0510 mov ds, ax mov si, 0x0510 mov al, byte ptr es:[di] # Save byte at es:di on stack. push ax # (we want to restore it later) mov al, byte ptr ds:[si] # Save byte at ds:si on stack. push ax # (we want to restore it later) mov byte ptr es:[di], 0x00 # [es:di] = 0x00 mov byte ptr ds:[si], 0xFF # [ds:si] = 0xff cmp byte ptr es:[di], 0xFF # Did memory wrap around? pop ax mov byte ptr ds:[si], al # Restore byte at ds:si pop ax mov byte ptr es:[di], al # Restore byte at es:di mov ax, 0 je check_a20__exit # If memory wrapped around, return 0. mov ax, 1 # else return 1. check_a20__exit: pop si # Restore saved registers. pop di pop es pop ds popf ret .endfunc
GDB调试信息
(gdb) r Starting program: /home/peter/Documents/.../hardware_assembly/checkA20_gas … (gdb) si 16 cli # No interrupts, please (gdb) si Program received signal SIGSEGV, Segmentation fault. CheckA20 () at checkA20_gas.s:16 16 cli # No interrupts, please
测试结果
# NASM版本运行结果: $ ./checkA20 zsh: segmentation fault (core dumped) ./checkA20 # GAS版本运行结果: $ ./checkA20_gas zsh: segmentation fault (core dumped) ./checkA20_gas # 仅测试cli指令的程序运行结果: $ ./poc_cli zsh: segmentation fault (core dumped) ./poc_cli
poc_cli.s代码
.intel_syntax noprefix .text .global _start _start: cli mov ebx, eax mov eax, 1 int 0x80
内容的提问来源于stack exchange,提问作者nostromo
相关产品推荐
相关产品推荐

