使用非规范地址检索内存数据会导致 SIGSEGV 而不是 SIGBUS [英] Retrieving memory data with non-canonical-address causes SIGSEGV rather than SIGBUS

查看:89
本文介绍了使用非规范地址检索内存数据会导致 SIGSEGV 而不是 SIGBUS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法产生总线错误";使用以下汇编代码.这里我使用的内存地址不是合法的规范地址".那么,我该如何触发该错误?

我在 Ubuntu 20.04 LTS 和 NASM 2.14.02 下运行这段代码,但它导致负载上出现 SIGSEGV 分段错误,而不是 SIGBUS.

全局 _start节.text_开始:mov rax, [qword 0x11223344557788]mov rax, 60xor rdi, rdi系统调用

编译后对应的X86-64汇编代码:

 .text 节的反汇编:0000000000401000 <_start>:401000: 48 a1 88 77 55 44 33 movabs 0x11223344557788,%rax401007:22 11 0040100a: b8 3c 00 00 00 mov $0x3c,%eax40100f: 48 31 ff xor %rdi,%rdi401012:0f 05 系统调用

解决方案

如果您查看

Linux 将所有 #GP 异常映射到 SIGSEGV 信号(分段错误).但是,在 Linux 中,非规范地址有一种方法会导致 总线错误,那就是让处理器引发 #SS(堆栈段)异常.Linux 将 #SS 异常映射到 SIGBUS 信号.将堆栈指针设置为非规范地址,然后执行与堆栈相关的操作会产生这样的异常.

这段代码应该会产生一个总线错误:

全局 _start节.text_开始:mov rsp, 0x8000000000000000 ;将 RSP 设置为非规范地址推拉克斯;在堆栈上推送值应该产生 BUS ERROR

在 Linux 上产生总线错误的另一种方法是引发 #AC(对齐检查)异常.如果您在 RFLAGS 中编写启用对齐检查位(位 18)的环 3(用户)代码并进行未对齐的内存访问,您还应该收到一个 SIGBUS 信号.此代码应产生一个总线错误:

全局 _start节.text_开始:推送;将当前 RFLAGS 放入堆栈或双字[rsp],1<<18;启用位 18(对齐检查);RFLAGS 值保存在堆栈中弹出;将新的 RFLAGS 标志值弹出到 RFLAGS 寄存器中mov eax, [rsp + 1] ;从未对齐的地址移动 DWORD 值;应该产生一个 BUS ERROR

I can not produce a "Bus error" with the following assembly code. Here the memory address I use is not a legal "canonical-address". So, how can I trigger that error?

I was running this snippet of code under Ubuntu 20.04 LTS with NASM 2.14.02, but it results in a SIGSEGV segmentation fault on the load, not SIGBUS.

global _start
section .text
_start:
    mov rax, [qword 0x11223344557788]
    mov rax, 60
    xor rdi, rdi
    syscall

Corresponding X86-64 assembly code after compiling:

Disassembly of section .text:

0000000000401000 <_start>:
  401000:   48 a1 88 77 55 44 33    movabs 0x11223344557788,%rax
  401007:   22 11 00 
  40100a:   b8 3c 00 00 00          mov    $0x3c,%eax
  40100f:   48 31 ff                xor    %rdi,%rdi
  401012:   0f 05                   syscall

解决方案

If you review the Instruction Set Architecture manual for the MOV instruction you would find that accessing a non-canonical address yields a #GP(0) General Protection Fault:

Linux maps all #GP exceptions to SIGSEGV signal (Segmentation Fault). However, in Linux there is a way for a non-canonical address to cause a Bus Error and that is by getting the processor to raise an #SS (Stack Segment) exception. Linux maps #SS exceptions to the SIGBUS signal. Setting the stack pointer to a non-canonical address and then performing a stack related operation will produce such an exception.

This code should produce a Bus Error:

global _start
section .text
_start:
    mov rsp, 0x8000000000000000 ; Set RSP to a non-canonical address
    push rax                    ; Pushing value on stack should produce BUS ERROR

One other way of producing a Bus Error on Linux is to raise an #AC (Alignment Check) exception. If you write ring 3 (user) code that enables the Alignment Check bit (bit 18) in RFLAGS and do an unaligned memory access you should also receive a SIGBUS signal. This code should produce a Bus Error:

global _start
section .text
_start:
    pushf                      ; Put current RFLAGS on the stack
    or dword [rsp], 1<<18      ; Enable bit 18 (Alignment Check) of the
                               ;     RFLAGS value saved on stack
    popf                       ; Pop new RFLAGS flags value into the RFLAGS register
    mov eax, [rsp + 1]         ; Move a DWORD value from unaligned address
                               ;     Should produce a BUS ERROR

这篇关于使用非规范地址检索内存数据会导致 SIGSEGV 而不是 SIGBUS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆