【问题标题】:What does the error "Segmentation fault(core dumped)" mean?错误“分段错误(核心转储)”是什么意思?
【发布时间】:2021-02-26 10:29:50
【问题描述】:

我正在尝试使用汇编程序编码实现一个 for 循环,并且在每次迭代中应该打印寄存器 edi 的值。当我尝试执行我的代码时,我收到错误“分段错误(核心转储)”。谁能告诉我这个错误是什么意思,我的代码有什么错误吗?

section .text
         global _start

_start:
        xor edi,edi

loop:    
        add edi,'0'
        
        ;print i
        mov edi,1
        mov esi,1
        mov ecx,[edi]
        mov edx,1
        syscall
        
        sub edi,'0'
        
        inc edi   
        cmp edi,5
        jl loop

【问题讨论】:

  • mov edi,1 会覆盖您之前拥有的 '0' 值,但它们都不是有效地址,因此尝试使用 [edi] 内存源操作数是没有意义的。此外,Linux 的 write syscall 采用 RSI 中的指针,并忽略 RCX(实际上,系统调用指令本身在内核获得控制之前写入 RCX。)我想知道您是否从使用 @987654326 的 32 位代码中复制了 ECX 部分@。 (它仍然是错误的......)

标签: linux assembly x86 segmentation-fault


【解决方案1】:

这意味着您试图以不允许的方式访问地址空间。例如:

  • 您可能曾尝试写入只读位置

  • 您可能试图从只写位置读取

  • 您可能曾尝试从未设置执行权限的位置执行代码

  • 你可能试图从一个根本没有映射的地址读取或写入,或者映射的所有类型的访问都不允许

还有其他一些条件会导致此信号跳闸。查看mmapmprotect 的手册页,了解可能的情况。

【讨论】:

  • 请注意,Linux 还为 x86 #GP 异常提供了 SIGSEGV,而不仅仅是无效页面错误 (#PF)。因此,例如,您可以通过尝试在用户空间中运行mov cr3, raxin al, 0x80 之类的特权指令或int 0x44 之类的无效中断来实现SIGSEGV。但是是的,在这种情况下,显然访问绝对地址1 是问题所在;即使您尝试使用 mmap,Linux 也会拒绝映射该页面,除非您更改 sysctl 设置:wiki.debian.org/mmap_min_addr
  • 严格来说 Linux 将不允许映射第一页。这有几个原因:NUL 指针存在于那里(在 Linux 上)以及通过“指针”错误代码发出的几个带内信号。同样也适用于第一个“负面”页面。基本上在 Linux 上,-4096…4095 范围内的任何地址都可以安全地假定为无效。如果你想知道负地址:内核就在那里(如果你将负指针指向它们的 uintptr_t 对应物,它们在上半部分)。
  • 确定该范围内的0..4095 部分吗? wiki.debian.org/mmap_min_addr 说一些用户空间的东西,比如用于 16 位用户空间的 WINE 和dosemu,需要 mmap_min_addr = 0。您对用于错误代码的首页并保留以防止被映射(Why can't I mmap(MAP_FIXED) the highest virtual page in a 32-bit Linux process on a 64-bit kernel?)是正确的,但是对于 4096 个可能的代码,它实际上并不需要更多。如果你想放弃 NULL-deref 实际上在用户空间出错的安全性,我认为内核允许它。
  • 事实上,根据我的链接问题,我当时确实尝试过,发现我可以使用该测试代码映射零页。
  • @PeterCordes 这取决于您的系统配置方式。如果我们可以在某些 ELF 标头字段中将其设置在每个可执行文件的基础上,那就太好了。问题的核心是,就 MMPU 而言,内存保护发生在页面级别。
猜你喜欢
  • 1970-01-01
  • 2020-03-16
  • 2017-01-26
  • 2013-11-07
  • 2014-08-04
  • 2012-11-19
相关资源
最近更新 更多