Linux可执行文件.data节的默认行为在5.4和5.9之间更改? [英] Linux default behavior of executable .data section changed between 5.4 and 5.9?

查看:96
本文介绍了Linux可执行文件.data节的默认行为在5.4和5.9之间更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不小心在 .data 部分中写了我的汇编代码.我编译并执行它.即使我未指定 execstack 之类的标志,该程序也可以在Linux 5.4.0-53-generic 下正常运行.

I accidentally wrote my Assembly code in the .data section. I compiled it and executed it. The program ran normally under Linux 5.4.0-53-generic even though I didn't specify a flag like execstack.

之后,我在Linux 5.9.0-050900rc5-generic 下执行了该程序.该程序得到了 SIGSEGV .我通过阅读/proc/$ pid/maps 检查了虚拟内存权限.原来,该部分不可执行.

After that, I executed the program under Linux 5.9.0-050900rc5-generic. The program got SIGSEGV. I inspected the virtual memory permission by reading /proc/$pid/maps. It turned out that the section is not executable.

我认为Linux上有一个配置可以管理该权限.但是我不知道在哪里找到.

I think there is a configuration on Linux that manages that permission. But I don't know where to find.

ammarfaizi2@integral:/tmp$ uname -r
5.4.0-53-generic
ammarfaizi2@integral:/tmp$ cat test.asm
[section .data]
global _start
_start:
  mov eax, 60
  xor edi, edi
  syscall
ammarfaizi2@integral:/tmp$ nasm --version
NASM version 2.14.02
ammarfaizi2@integral:/tmp$ nasm -felf64 test.asm -o test.o
ammarfaizi2@integral:/tmp$ ld test.o -o test
ammarfaizi2@integral:/tmp$ ./test
ammarfaizi2@integral:/tmp$ echo $?
0
ammarfaizi2@integral:/tmp$ md5sum test
7ffff5fd44e6ff0a278e881732fba525  test
ammarfaizi2@integral:/tmp$ 

检查权限(00400000-00402000 rwxp),因此它是可执行的.

## Debug
gef➤  shell cat /proc/`pgrep test`/maps
00400000-00402000 rwxp 00000000 08:03 7471589                            /tmp/test
7ffff7ffb000-7ffff7ffe000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffe000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
gef➤

[Linux 5.9.0-050900rc5-generic]

运行(段错误)

root@esteh:/tmp# uname -r
5.9.0-050900rc5-generic
root@esteh:/tmp# cat test.asm
[section .data]
global _start
_start:
  mov eax, 60
  xor edi, edi
  syscall
root@esteh:/tmp# nasm --version
NASM version 2.14.02
root@esteh:/tmp# nasm -felf64 test.asm -o test.o
root@esteh:/tmp# ld test.o -o test
root@esteh:/tmp# ./test
Segmentation fault (core dumped)
root@esteh:/tmp# echo $?
139
root@esteh:/tmp# md5sum test
7ffff5fd44e6ff0a278e881732fba525  test
root@esteh:/tmp# 

检查权限(00400000-00402000 rw-p),因此它不可执行.

## Debug
gef➤  shell cat /proc/`pgrep test`/maps
00400000-00402000 rw-p 00000000 fc:01 2412                               /tmp/test
7ffff7ff9000-7ffff7ffd000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
gef➤  

objdump -p

root@esteh:/tmp# objdump -p test

test:     file format elf64-x86-64

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**12
         filesz 0x0000000000001009 memsz 0x0000000000001009 flags rw-

问题

  1. Linux上用于管理默认ELF节权限的配置在哪里?
  2. 我对权限的观察正确吗?

摘要

  • Linux 5.4.0-53-generic .data 部分的默认权限是可执行的.
  • Linux 5.9.0-050900rc5-generic .data 部分的默认权限是 NOT 可执行文件.
  • Summary

    • Default permission for .data section on Linux 5.4.0-53-generic is executable.
    • Default permission for .data section on Linux 5.9.0-050900rc5-generic is NOT executable.
    • 推荐答案

      这只是一个猜测:我认为罪魁祸首是自动设置的 READ_IMPLIES_EXEC 个性在没有 PT_GNU_STACK 段的情况下.

      This is only a guess: I think the culprit is the READ_IMPLIES_EXEC personality that was being set automatically in the absence of a PT_GNU_STACK segment.

      5.4内核源代码中,我们可以找到此文件一段代码:

      SET_PERSONALITY2(loc->elf_ex, &arch_state);
      if (elf_read_implies_exec(loc->elf_ex, executable_stack))
          current->personality |= READ_IMPLIES_EXEC;
      

      这是唯一可以将RW部分转换为RWX部分的东西.对我来说, PROC_EXEC 的任何其他使用似乎都没有改变或与此问题相关.

      That's the only thing that can transform an RW section into an RWX one. Any other use of PROC_EXEC didn't seem to be changed or relevant to this question, to me.

      executable_stack 设置为但是,如果不存在 PT_GNU_STACK 段,则该变量将保留

      But if the PT_GNU_STACK segment is not present, that variable retains its default value:

      int executable_stack = EXSTACK_DEFAULT;
      

      现在此工作流程在5.4和最新的内核源代码中都是相同的,更改的是 elf_read_implies_exec 的定义:

      Now this workflow is identical in both 5.4 and the latest kernel source, what changed is the definition of elf_read_implies_exec:

      Linux 5.4 :

      /*
       * An executable for which elf_read_implies_exec() returns TRUE will
       * have the READ_IMPLIES_EXEC personality flag set automatically.
       */
      #define elf_read_implies_exec(ex, executable_stack) \
          (executable_stack != EXSTACK_DISABLE_X)
      

      最新的Linux :

      /*
       * An executable for which elf_read_implies_exec() returns TRUE will
       * have the READ_IMPLIES_EXEC personality flag set automatically.
       *
       * The decision process for determining the results are:
       *
       *                 CPU: | lacks NX*  | has NX, ia32     | has NX, x86_64 |
       * ELF:                 |            |                  |                |
       * ---------------------|------------|------------------|----------------|
       * missing PT_GNU_STACK | exec-all   | exec-all         | exec-none      |
       * PT_GNU_STACK == RWX  | exec-stack | exec-stack       | exec-stack     |
       * PT_GNU_STACK == RW   | exec-none  | exec-none        | exec-none      |
       *
       *  exec-all  : all PROT_READ user mappings are executable, except when
       *              backed by files on a noexec-filesystem.
       *  exec-none : only PROT_EXEC user mappings are executable.
       *  exec-stack: only the stack and PROT_EXEC user mappings are executable.
       *
       *  *this column has no architectural effect: NX markings are ignored by
       *   hardware, but may have behavioral effects when "wants X" collides with
       *   "cannot be X" constraints in memory permission flags, as in
       *   https://lkml.kernel.org/r/20190418055759.GA3155@mellanox.com
       *
       */
      #define elf_read_implies_exec(ex, executable_stack) \
          (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
      

      请注意,在5.4版本中,如果堆栈未显式标记为不可执行(通过 PT_GNU_STACK 段).

      Note how in the 5.4 version the elf_read_implies_exec returned a true value if the stack was not explicitly marked as not executable (via the PT_GNU_STACK segment).

      在最新消息中,此检查现在更具防御性:如果在以下位置未找到 PT_GNU_STACK 段,则 elf_read_implies_exec 仅在32位可执行文件上为trueELF二进制文件.

      In the latest source, the check is now more defensive: the elf_read_implies_exec is true only on 32-bit executable, in the case where no PT_GNU_STACK segment was found in the ELF binary.

      我汇编了程序,将其链接起来,没有找到 PT_GNU_STACK 段,因此可能是 的原因.如果确实是问题所在,并且如果我正确地遵循了代码,那么如果您将堆栈设置为二进制可执行文件,则其数据部分将不再被映射为可执行文件(即使在Linux 5.4上也是如此).

      I assembled your program, linked it, and found no PT_GNU_STACK segment, so this may be the reason.
      If this is indeed the issue and if I followed the code correctly, if you set the stack as not executable in the binary, its data section should not be mapped executable anymore (not even on Linux 5.4).

      这篇关于Linux可执行文件.data节的默认行为在5.4和5.9之间更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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